From b05ca6e4036f3290ce091caaa903733b6afb7b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Capucho?= Date: Wed, 11 Aug 2021 14:44:14 +0100 Subject: [PATCH] [glsl-in] Builtin redefinition and calls fixes --- src/front/glsl/ast.rs | 25 +- src/front/glsl/builtins.rs | 1633 +++++++++++++++++++++++ src/front/glsl/context.rs | 15 +- src/front/glsl/error.rs | 19 - src/front/glsl/functions.rs | 1113 ++++----------- src/front/glsl/mod.rs | 1 + src/front/glsl/parser.rs | 12 +- src/front/glsl/parser/expressions.rs | 1 - src/front/glsl/types.rs | 11 +- tests/out/wgsl/246-collatz-comp.wgsl | 22 +- tests/out/wgsl/bevy-pbr-frag.wgsl | 676 +++++----- tests/out/wgsl/bool-select-frag.wgsl | 6 +- tests/out/wgsl/clamp-splat-vert.wgsl | 4 +- tests/out/wgsl/math-functions-vert.wgsl | 169 +-- 14 files changed, 2396 insertions(+), 1311 deletions(-) create mode 100644 src/front/glsl/builtins.rs diff --git a/src/front/glsl/ast.rs b/src/front/glsl/ast.rs index b2e35741c0..f449c661db 100644 --- a/src/front/glsl/ast.rs +++ b/src/front/glsl/ast.rs @@ -1,4 +1,6 @@ -use super::SourceMetadata; +use std::fmt; + +use super::{builtins::MacroCall, SourceMetadata}; use crate::{ BinaryOperator, Binding, Constant, Expression, Function, GlobalVariable, Handle, Interpolation, Sampling, StorageAccess, StorageClass, Type, UnaryOperator, @@ -26,12 +28,31 @@ pub struct ParameterInfo { pub depth: bool, } +/// How the function is implemented +#[derive(Clone, Copy)] +pub enum FunctionKind { + /// The function is user defined + Call(Handle), + /// The function is a buitin + Macro(MacroCall), +} + +impl fmt::Debug for FunctionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Self::Call(_) => write!(f, "Call"), + Self::Macro(_) => write!(f, "Macro"), + } + } +} + #[derive(Debug)] pub struct FunctionDeclaration { /// Normalized function parameters, modifiers are not applied pub parameters: Vec>, pub parameters_info: Vec, - pub handle: Handle, + /// How the function is implemented + pub kind: FunctionKind, /// Wheter this function was already defined or is just a prototype pub defined: bool, /// Wheter or not this function returns void (nothing) diff --git a/src/front/glsl/builtins.rs b/src/front/glsl/builtins.rs new file mode 100644 index 0000000000..7d45d44c16 --- /dev/null +++ b/src/front/glsl/builtins.rs @@ -0,0 +1,1633 @@ +use super::{ + ast::{FunctionDeclaration, FunctionKind, ParameterInfo, ParameterQualifier}, + context::Context, + Error, ErrorKind, Parser, Result, SourceMetadata, +}; +use crate::{ + BinaryOperator, Block, Expression, Handle, ImageClass, ImageDimension, ImageQuery, + MathFunction, Module, RelationalFunction, SampleLevel, Span, Type, TypeInner, VectorSize, +}; + +impl Module { + /// Helper function, to create a function prototype for a builtin + fn add_builtin(&mut self, args: Vec, builtin: MacroCall) -> FunctionDeclaration { + let mut parameters = Vec::with_capacity(args.len()); + let mut parameters_info = Vec::with_capacity(args.len()); + + for arg in args { + parameters.push(self.types.fetch_or_append( + Type { + name: None, + inner: arg, + }, + Span::Unknown, + )); + parameters_info.push(ParameterInfo { + qualifier: ParameterQualifier::In, + depth: false, + }); + } + + FunctionDeclaration { + parameters, + parameters_info, + kind: FunctionKind::Macro(builtin), + defined: false, + void: false, + } + } +} + +impl Parser { + /// Injects a builtin into the [`lookup_function`](Self::lookup_function) + /// + /// This is done to not add a large startup cost and not increase memory + /// usage if it isn't needed. + pub(crate) fn inject_builtin(&mut self, name: String) { + use crate::{ImageDimension as Dim, ScalarKind as Sk}; + + let declarations = self.lookup_function.entry(name.clone()).or_default(); + + match name.as_str() { + "sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS" + | "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => declarations + .push(self.module.add_builtin( + vec![ + TypeInner::Image { + dim: match name.as_str() { + "sampler1D" | "sampler1DArray" => Dim::D1, + "sampler2D" | "sampler2DArray" | "sampler2DMS" + | "sampler2DMSArray" => Dim::D2, + "sampler3D" => Dim::D3, + _ => Dim::Cube, + }, + arrayed: matches!( + name.as_str(), + "sampler1DArray" + | "sampler2DArray" + | "sampler2DMSArray" + | "samplerCubeArray" + ), + class: ImageClass::Sampled { + kind: Sk::Float, + multi: matches!(name.as_str(), "sampler2DMS" | "sampler2DMSArray"), + }, + }, + TypeInner::Sampler { comparison: false }, + ], + MacroCall::Sampler, + )), + "sampler1DShadow" + | "sampler1DArrayShadow" + | "sampler2DShadow" + | "sampler2DArrayShadow" + | "samplerCubeShadow" + | "samplerCubeArrayShadow" => { + let dim = match name.as_str() { + "sampler1DShadow" | "sampler1DArrayShadow" => Dim::D1, + "sampler2DShadow" | "sampler2DArrayShadow" => Dim::D2, + _ => Dim::Cube, + }; + let arrayed = matches!( + name.as_str(), + "sampler1DArrayShadow" | "sampler2DArrayShadow" | "samplerCubeArrayShadow" + ); + + for i in 0..2 { + let ty = TypeInner::Image { + dim, + arrayed, + class: match i { + 0 => ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + _ => ImageClass::Depth { multi: false }, + }, + }; + + declarations.push(self.module.add_builtin( + vec![ty, TypeInner::Sampler { comparison: true }], + MacroCall::SamplerShadow, + )) + } + } + "texture" | "textureLod" => { + // bits layout + // bits 0 trough 1 - dims + // bit 2 - shadow + // bit 3 - array + // bit 4 - !bias + // + // 0b11111 is the latest since there are not 3D arrayed shadowed + // textures and cube arrayed shadows textures always have a + // compare argument + for bits in 0..(0b100000) { + let dim = bits & 0b11; + let shadow = bits & 0b100 == 0b100; + let arrayed = bits & 0b1000 == 0b1000; + let bias = bits & 0b10000 == 0b00000; + let builtin = match name.as_str() { + "texture" => MacroCall::Texture, + _ => MacroCall::TextureLod, + }; + + // Shadow, arrayed or both 3D images are not allowed + if (shadow || arrayed) && dim == 0b11 + || (builtin == MacroCall::TextureLod + && (dim != 0b00 && shadow && arrayed || dim == 0b10 && shadow || !bias)) + { + continue; + } + + let class = match shadow { + true => ImageClass::Depth { multi: false }, + false => ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + }; + + let image = TypeInner::Image { + dim: match dim { + 0b00 => Dim::D1, + 0b01 => Dim::D2, + 0b10 => Dim::Cube, + _ => Dim::D3, + }, + arrayed, + class, + }; + + let vector = match (dim, shadow) { + (0b00, false) => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + (0b00, true) | (0b11, _) => TypeInner::Vector { + size: VectorSize::Tri, + kind: Sk::Float, + width: 4, + }, + (_, _) => { + let size = match dim + arrayed as u32 + shadow as u32 { + 1 => VectorSize::Bi, + 2 => VectorSize::Tri, + _ => VectorSize::Quad, + }; + + TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + } + } + }; + + let mut args = vec![image, vector]; + + if bias { + args.push(TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }) + } + + declarations.push(self.module.add_builtin(args, builtin)) + } + } + "textureProj" => { + // bits layout + // bit 0 - shadow + // bit 1 - bias + // bits 2 trough 3 - dims + // + // 0b0111 is the latest since there are only 1D and 2D shadow + // variants + for bits in 0..(0b1000) { + let dim = bits >> 2; + let shadow = bits & 0b1 == 0b1; + let bias = bits & 0b10 == 0b10; + + let class = match shadow { + true => ImageClass::Depth { multi: false }, + false => ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + }; + + let image = TypeInner::Image { + dim: match dim { + 0b00 => Dim::D1, + 0b01 => Dim::D2, + _ => Dim::Cube, + }, + arrayed: false, + class, + }; + + let vector = TypeInner::Vector { + size: VectorSize::Quad, + kind: Sk::Float, + width: 4, + }; + + let mut args = vec![image, vector]; + + if bias { + args.push(TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }) + } + + declarations.push(self.module.add_builtin(args, MacroCall::TextureProj)) + } + } + "textureGrad" => { + // bits layout + // bits 0 trough 1 - dims + // bit 2 - shadow + // bit 3 - array + // + // 0b1010 is the latest since there are no 3D arrayed shadowed + // textures and cube arrayed shadows textures are not allowed + for bits in 0..(0b1011) { + let dim = bits & 0b11; + let shadow = bits & 0b100 == 0b100; + let arrayed = bits & 0b1000 == 0b1000; + + // Shadow, arrayed or both 3D images are not allowed + if shadow && dim == 0b11 + // samplerCubeArrayShadow is not allowed + || shadow && arrayed && dim == 0b10 + { + continue; + } + + let class = match shadow { + true => ImageClass::Depth { multi: false }, + false => ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + }; + + let image = TypeInner::Image { + dim: match dim { + 0b00 => Dim::D1, + 0b01 => Dim::D2, + 0b10 => Dim::Cube, + _ => Dim::D3, + }, + arrayed, + class, + }; + + let vector = match (dim, shadow) { + (0b00, false) => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + (0b00, true) | (0b11, _) => TypeInner::Vector { + size: VectorSize::Tri, + kind: Sk::Float, + width: 4, + }, + (_, _) => { + let size = match dim + arrayed as u32 + shadow as u32 { + 1 => VectorSize::Bi, + 2 => VectorSize::Tri, + _ => VectorSize::Quad, + }; + + TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + } + } + }; + + let size = match dim { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + _ => Some(VectorSize::Tri), + }; + + let ty = || match size { + None => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + }, + }; + + let args = vec![image, vector, ty(), ty()]; + + declarations.push(self.module.add_builtin(args, MacroCall::TextureGrad)) + } + } + "textureSize" => { + // bits layout + // bits 0 trough 1 - dims + // bit 2 - shadow + // bit 3 - array + for bits in 0..(0b10000) { + let dim = bits & 0b11; + let shadow = bits & 0b100 == 0b100; + let arrayed = bits & 0b1000 == 0b1000; + + // Shadow, arrayed or both 3D images are not allowed + if (shadow || arrayed) && dim == 0b11 { + continue; + } + + let class = match shadow { + true => ImageClass::Depth { multi: false }, + false => ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + }; + + let image = TypeInner::Image { + dim: match dim { + 0b00 => Dim::D1, + 0b01 => Dim::D2, + 0b10 => Dim::Cube, + _ => Dim::D3, + }, + arrayed, + class, + }; + + let args = vec![ + image, + TypeInner::Scalar { + kind: Sk::Sint, + width: 4, + }, + ]; + + declarations.push(self.module.add_builtin(args, MacroCall::TextureSize)) + } + } + "texelFetch" => { + // bits layout + // bit 0 - dim part 1 - 1D/2D + // bit 1 - array + // bit 2 - dim part 2 - 3D + // + // 0b100 is the latest since 3D arrayed images aren't allowed + for bits in 0..(0b101) { + let dim = bits & 0b1 | (bits & 0b100) >> 1; + let arrayed = bits & 0b1000 == 0b1000; + + let image = TypeInner::Image { + dim: match dim { + 0b00 => Dim::D1, + 0b01 => Dim::D2, + _ => Dim::D3, + }, + arrayed, + class: ImageClass::Sampled { + kind: Sk::Float, + multi: false, + }, + }; + + let vector = match (dim, arrayed) { + (0b00, false) => TypeInner::Scalar { + kind: Sk::Sint, + width: 4, + }, + (_, _) => { + let size = match dim + arrayed as u32 { + 1 => VectorSize::Bi, + 2 => VectorSize::Tri, + _ => VectorSize::Quad, + }; + + TypeInner::Vector { + size, + kind: Sk::Sint, + width: 4, + } + } + }; + + let args = vec![ + image, + vector, + TypeInner::Scalar { + kind: Sk::Sint, + width: 4, + }, + ]; + + declarations.push(self.module.add_builtin(args, MacroCall::TexelFetch)) + } + } + "ceil" | "round" | "floor" | "fract" | "trunc" | "sqrt" | "inversesqrt" + | "normalize" | "length" | "isinf" | "isnan" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let width = (bits & 0b1) * 4 + 4; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + let args = vec![match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }]; + + let fun = match name.as_str() { + "ceil" => MacroCall::MathFunction(MathFunction::Ceil), + "round" => MacroCall::MathFunction(MathFunction::Round), + "floor" => MacroCall::MathFunction(MathFunction::Floor), + "fract" => MacroCall::MathFunction(MathFunction::Fract), + "trunc" => MacroCall::MathFunction(MathFunction::Trunc), + "sqrt" => MacroCall::MathFunction(MathFunction::Sqrt), + "inversesqrt" => MacroCall::MathFunction(MathFunction::InverseSqrt), + "normalize" => MacroCall::MathFunction(MathFunction::Normalize), + "length" => MacroCall::MathFunction(MathFunction::Length), + "isinf" => MacroCall::Relational(RelationalFunction::IsInf), + "isnan" => MacroCall::Relational(RelationalFunction::IsNan), + _ => unreachable!(), + }; + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "dot" | "reflect" | "distance" | "ldexp" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let width = (bits & 0b1) * 4 + 4; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + let ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }; + + let fun = match name.as_str() { + "dot" => MacroCall::MathFunction(MathFunction::Dot), + "reflect" => MacroCall::MathFunction(MathFunction::Reflect), + "distance" => MacroCall::MathFunction(MathFunction::Distance), + "ldexp" => MacroCall::MathFunction(MathFunction::Ldexp), + _ => unreachable!(), + }; + + declarations.push(self.module.add_builtin(vec![ty(), ty()], fun)) + } + } + "sin" | "exp" | "exp2" | "sinh" | "cos" | "cosh" | "tan" | "tanh" | "acos" | "asin" + | "log" | "log2" => { + // bits layout + // bit 0 trough 1 - dims + for bits in 0..(0b100) { + let size = match bits { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + declarations.push(self.module.add_builtin( + vec![match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + }], + MacroCall::MathFunction(match name.as_str() { + "sin" => MathFunction::Sin, + "exp" => MathFunction::Exp, + "exp2" => MathFunction::Exp2, + "sinh" => MathFunction::Sinh, + "cos" => MathFunction::Cos, + "cosh" => MathFunction::Cosh, + "tan" => MathFunction::Tan, + "tanh" => MathFunction::Tanh, + "acos" => MathFunction::Acos, + "asin" => MathFunction::Asin, + "log" => MathFunction::Log, + "log2" => MathFunction::Log2, + _ => unreachable!(), + }), + )) + } + } + "pow" => { + // bits layout + // bit 0 trough 1 - dims + for bits in 0..(0b100) { + let size = match bits { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + let ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + }; + + declarations.push( + self.module.add_builtin( + vec![ty(), ty()], + MacroCall::MathFunction(MathFunction::Pow), + ), + ) + } + } + "transpose" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 4 - dims + for bits in 0..(0b10010) { + let width = (bits & 0b1) * 4 + 4; + let (rows, columns) = match bits >> 1 { + 0b0000 => (VectorSize::Bi, VectorSize::Bi), + 0b0001 => (VectorSize::Bi, VectorSize::Tri), + 0b0010 => (VectorSize::Bi, VectorSize::Quad), + 0b0011 => (VectorSize::Tri, VectorSize::Bi), + 0b0100 => (VectorSize::Tri, VectorSize::Tri), + 0b0101 => (VectorSize::Tri, VectorSize::Quad), + 0b0110 => (VectorSize::Quad, VectorSize::Bi), + 0b0111 => (VectorSize::Quad, VectorSize::Tri), + _ => (VectorSize::Quad, VectorSize::Quad), + }; + + if (bits >> 1) > 0b1000 { + continue; + } + + declarations.push(self.module.add_builtin( + vec![TypeInner::Matrix { + columns, + rows, + width, + }], + MacroCall::MathFunction(MathFunction::Transpose), + )) + } + } + "inverse" | "determinant" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b110) { + let width = (bits & 0b1) * 4 + 4; + let (rows, columns) = match bits >> 1 { + 0b00 => (VectorSize::Bi, VectorSize::Bi), + 0b01 => (VectorSize::Tri, VectorSize::Tri), + _ => (VectorSize::Quad, VectorSize::Quad), + }; + + let args = vec![TypeInner::Matrix { + columns, + rows, + width, + }]; + + declarations.push(self.module.add_builtin( + args, + MacroCall::MathFunction(match name.as_str() { + "inverse" => MathFunction::Inverse, + "determinant" => MathFunction::Determinant, + _ => unreachable!(), + }), + )) + } + } + "abs" | "sign" => { + // bits layout + // bit 0 trough 1 - dims + // bit 2 trough 3 - kind + for bits in 0..(0b1100) { + let size = match bits & 0b11 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + let (kind, width) = match bits >> 2 { + 0b00 => (Sk::Float, 4), + 0b01 => (Sk::Sint, 4), + _ => (Sk::Float, 8), + }; + + let args = vec![match size { + Some(size) => TypeInner::Vector { size, kind, width }, + None => TypeInner::Scalar { kind, width }, + }]; + + declarations.push(self.module.add_builtin( + args, + MacroCall::MathFunction(match name.as_str() { + "abs" => MathFunction::Abs, + "sign" => MathFunction::Sign, + _ => unreachable!(), + }), + )) + } + } + "bitCount" | "bitfieldReverse" => { + // bits layout + // bit 0 - int/uint + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let kind = match bits & 0b1 { + 0b0 => Sk::Sint, + _ => Sk::Uint, + }; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + let args = vec![match size { + Some(size) => TypeInner::Vector { + size, + kind, + width: 4, + }, + None => TypeInner::Scalar { kind, width: 4 }, + }]; + + declarations.push(self.module.add_builtin( + args, + MacroCall::MathFunction(match name.as_str() { + "bitCount" => MathFunction::CountOneBits, + "bitfieldReverse" => MathFunction::ReverseBits, + _ => unreachable!(), + }), + )) + } + } + "atan" => { + // bits layout + // bit 0 - atan/atan2 + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let fun = match bits & 0b1 { + 0b0 => MathFunction::Atan, + _ => MathFunction::Atan2, + }; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + let ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width: 4, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + }; + + let mut args = vec![ty()]; + + if fun == MathFunction::Atan2 { + args.push(ty()) + } + + declarations.push(self.module.add_builtin(args, MacroCall::MathFunction(fun))) + } + } + "all" | "any" => { + // bits layout + // bit 0 trough 1 - dims + for bits in 0..(0b11) { + let size = match bits { + 0b00 => VectorSize::Bi, + 0b01 => VectorSize::Tri, + _ => VectorSize::Quad, + }; + + let args = vec![TypeInner::Vector { + size, + kind: Sk::Bool, + width: crate::BOOL_WIDTH, + }]; + + let fun = MacroCall::Relational(match name.as_str() { + "all" => RelationalFunction::All, + "any" => RelationalFunction::Any, + _ => unreachable!(), + }); + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal" + | "notEqual" => { + for bits in 0..(0b1001) { + let (size, kind) = match bits { + 0b0000 => (VectorSize::Bi, Sk::Float), + 0b0001 => (VectorSize::Tri, Sk::Float), + 0b0010 => (VectorSize::Quad, Sk::Float), + 0b0011 => (VectorSize::Bi, Sk::Sint), + 0b0100 => (VectorSize::Tri, Sk::Sint), + 0b0101 => (VectorSize::Quad, Sk::Sint), + 0b0110 => (VectorSize::Bi, Sk::Uint), + 0b0111 => (VectorSize::Tri, Sk::Uint), + _ => (VectorSize::Quad, Sk::Uint), + }; + + let ty = || TypeInner::Vector { + size, + kind, + width: 4, + }; + let args = vec![ty(), ty()]; + + let fun = MacroCall::Binary(match name.as_str() { + "lessThan" => BinaryOperator::Less, + "greaterThan" => BinaryOperator::Greater, + "lessThanEqual" => BinaryOperator::LessEqual, + "greaterThanEqual" => BinaryOperator::GreaterEqual, + "equal" => BinaryOperator::Equal, + "notEqual" => BinaryOperator::NotEqual, + _ => unreachable!(), + }); + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "mod" | "step" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 3 - dims + for bits in 0..(0b1110) { + let width = (bits & 0b1) * 4 + 4; + let (size, second_size) = match bits >> 1 { + 0b000 => (None, None), + 0b001 => (Some(VectorSize::Bi), None), + 0b010 => (Some(VectorSize::Tri), None), + 0b011 => (Some(VectorSize::Quad), None), + 0b100 => (Some(VectorSize::Bi), Some(VectorSize::Bi)), + 0b101 => (Some(VectorSize::Tri), Some(VectorSize::Tri)), + _ => (Some(VectorSize::Quad), Some(VectorSize::Quad)), + }; + + let mut args = Vec::with_capacity(2); + let step = name.as_str() == "step"; + + for i in 0..2 { + let maybe_size = match i == step as u32 { + true => size, + false => second_size, + }; + + args.push(match maybe_size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }) + } + + let fun = match name.as_str() { + "mod" => MacroCall::Mod(size), + "step" => MacroCall::Splatted(MathFunction::Step, size, 0), + _ => unreachable!(), + }; + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "min" | "max" => { + // bits layout + // bit 0 trough 1 - scalar kind and width + // bit 2 trough 4 - dims + for bits in 0..(0b11100) { + let (kind, width) = match bits & 0b11 { + 0b00 => (Sk::Float, 4), + 0b01 => (Sk::Float, 8), + 0b10 => (Sk::Sint, 4), + _ => (Sk::Uint, 4), + }; + let (size, second_size) = match bits >> 2 { + 0b000 => (None, None), + 0b001 => (Some(VectorSize::Bi), None), + 0b010 => (Some(VectorSize::Tri), None), + 0b011 => (Some(VectorSize::Quad), None), + 0b100 => (Some(VectorSize::Bi), Some(VectorSize::Bi)), + 0b101 => (Some(VectorSize::Tri), Some(VectorSize::Tri)), + _ => (Some(VectorSize::Quad), Some(VectorSize::Quad)), + }; + + let args = vec![ + match size { + Some(size) => TypeInner::Vector { size, kind, width }, + None => TypeInner::Scalar { kind, width }, + }, + match second_size { + Some(size) => TypeInner::Vector { size, kind, width }, + None => TypeInner::Scalar { kind, width }, + }, + ]; + + let fun = match name.as_str() { + "max" => MacroCall::Splatted(MathFunction::Max, size, 1), + "min" => MacroCall::Splatted(MathFunction::Min, size, 1), + _ => unreachable!(), + }; + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "modf" | "frexp" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let width = (bits & 0b1) * 4 + 4; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + let ty = self.module.types.fetch_or_append( + Type { + name: None, + inner: match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }, + }, + Span::Unknown, + ); + + let parameters = vec![ty, ty]; + + let fun = match name.as_str() { + "modf" => MacroCall::MathFunction(MathFunction::Modf), + "frexp" => MacroCall::MathFunction(MathFunction::Frexp), + _ => unreachable!(), + }; + + declarations.push(FunctionDeclaration { + parameters, + parameters_info: vec![ + ParameterInfo { + qualifier: ParameterQualifier::In, + depth: false, + }, + ParameterInfo { + qualifier: ParameterQualifier::Out, + depth: false, + }, + ], + kind: FunctionKind::Macro(fun), + defined: false, + void: false, + }) + } + } + "cross" => { + // bits layout + // bit 0 - float/double + for bits in 0..0b10 { + let width = bits * 4 + 4; + + let args = vec![ + TypeInner::Vector { + size: VectorSize::Tri, + kind: Sk::Float, + width, + }, + TypeInner::Vector { + size: VectorSize::Tri, + kind: Sk::Float, + width, + }, + ]; + + declarations.push( + self.module + .add_builtin(args, MacroCall::MathFunction(MathFunction::Cross)), + ) + } + } + "outerProduct" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 4 - dims + for bits in 0..(0b10010) { + let width = (bits & 0b1) * 4 + 4; + let (size1, size2) = match bits >> 1 { + 0b0000 => (VectorSize::Bi, VectorSize::Bi), + 0b0001 => (VectorSize::Bi, VectorSize::Tri), + 0b0010 => (VectorSize::Bi, VectorSize::Quad), + 0b0011 => (VectorSize::Tri, VectorSize::Bi), + 0b0100 => (VectorSize::Tri, VectorSize::Tri), + 0b0101 => (VectorSize::Tri, VectorSize::Quad), + 0b0110 => (VectorSize::Quad, VectorSize::Bi), + 0b0111 => (VectorSize::Quad, VectorSize::Tri), + _ => (VectorSize::Quad, VectorSize::Quad), + }; + + if (bits >> 1) > 0b1000 { + continue; + } + + let args = vec![ + TypeInner::Vector { + size: size1, + kind: Sk::Float, + width, + }, + TypeInner::Vector { + size: size2, + kind: Sk::Float, + width, + }, + ]; + + declarations.push( + self.module + .add_builtin(args, MacroCall::MathFunction(MathFunction::Outer)), + ) + } + } + "mix" => { + // bits layout + // bit 0 trough 2 - types + // bit 3 trough 4 - dims + for bits in 0..(0b100000) { + let (kind, width, splatted, boolean) = match bits & 0b111 { + 0b000 => (Sk::Sint, 4, false, true), + 0b001 => (Sk::Uint, 4, false, true), + 0b010 => (Sk::Float, 4, false, true), + 0b011 => (Sk::Float, 8, false, true), + 0b100 => (Sk::Float, 4, true, false), + 0b101 => (Sk::Float, 8, true, false), + 0b110 => (Sk::Float, 4, false, false), + _ => (Sk::Float, 8, false, false), + }; + let size = match bits >> 3 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + if splatted && size.is_none() { + continue; + } + + let ty = |kind, width| match size { + Some(size) => TypeInner::Vector { size, kind, width }, + None => TypeInner::Scalar { kind, width }, + }; + let args = vec![ + ty(kind, width), + ty(kind, width), + match (boolean, splatted) { + (true, _) => ty(Sk::Bool, crate::BOOL_WIDTH), + (_, false) => TypeInner::Scalar { kind, width }, + _ => ty(kind, width), + }, + ]; + + declarations.push(self.module.add_builtin( + args, + match boolean { + true => MacroCall::MixBoolean, + false => MacroCall::Splatted(MathFunction::Mix, size, 2), + }, + )) + } + } + "clamp" => { + // bits layout + // bit 0 trough 1 - float/double/int/uint + // bit 2 trough 3 - dims + // bit 4 - splatted + for bits in 0..(0b100000) { + let (kind, width) = match bits & 0b11 { + 0b00 => (Sk::Float, 4), + 0b01 => (Sk::Float, 8), + 0b10 => (Sk::Sint, 4), + _ => (Sk::Uint, 4), + }; + let size = match (bits >> 2) & 0b11 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + let splatted = bits & 0b10000 == 0b10000; + + if splatted && size.is_none() { + continue; + } + + let base_ty = || match size { + Some(size) => TypeInner::Vector { size, kind, width }, + None => TypeInner::Scalar { kind, width }, + }; + let limit_ty = || match splatted { + true => TypeInner::Scalar { kind, width }, + false => base_ty(), + }; + + let args = vec![base_ty(), limit_ty(), limit_ty()]; + + declarations.push(self.module.add_builtin(args, MacroCall::Clamp(size))) + } + } + "faceforward" | "fma" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let width = (bits & 0b1) * 4 + 4; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + let ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }; + let args = vec![ty(), ty(), ty()]; + + let fun = match name.as_str() { + "faceforward" => MacroCall::MathFunction(MathFunction::FaceForward), + "fma" => MacroCall::MathFunction(MathFunction::Fma), + _ => unreachable!(), + }; + + declarations.push(self.module.add_builtin(args, fun)) + } + } + "refract" => { + // bits layout + // bit 0 - float/double + // bit 1 trough 2 - dims + for bits in 0..(0b1000) { + let width = (bits & 0b1) * 4 + 4; + let size = match bits >> 1 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + let ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }; + let args = vec![ + ty(), + ty(), + TypeInner::Scalar { + kind: Sk::Float, + width: 4, + }, + ]; + declarations.push( + self.module + .add_builtin(args, MacroCall::MathFunction(MathFunction::Refract)), + ) + } + } + "smoothstep" => { + // bits layout + // bit 0 - float/double + // bit 1 - splatted + // bit 2 trough 3 - dims + for bits in 0..(0b10000) { + let width = (bits & 0b1) * 4 + 4; + let splatted = bits & 0b10 == 0b10; + let size = match bits >> 2 { + 0b00 => None, + 0b01 => Some(VectorSize::Bi), + 0b10 => Some(VectorSize::Tri), + _ => Some(VectorSize::Quad), + }; + + if splatted && size.is_none() { + continue; + } + + let base_ty = || match size { + Some(size) => TypeInner::Vector { + size, + kind: Sk::Float, + width, + }, + None => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + }; + let ty = || match splatted { + true => TypeInner::Scalar { + kind: Sk::Float, + width, + }, + false => base_ty(), + }; + declarations.push(self.module.add_builtin( + vec![ty(), ty(), base_ty()], + MacroCall::MathFunction(MathFunction::SmoothStep), + )) + } + } + // Not a builtin (or at lest not yet handled) + _ => {} + } + } +} + +/// A compiler defined builtin function +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum MacroCall { + Sampler, + SamplerShadow, + Texture, + TextureLod, + TextureProj, + TextureGrad, + TextureSize, + TexelFetch, + MathFunction(MathFunction), + Relational(RelationalFunction), + Binary(BinaryOperator), + Mod(Option), + Splatted(MathFunction, Option, usize), + MixBoolean, + Clamp(Option), +} + +impl MacroCall { + /// Adds the necessary expressions and statements to the passed body and + /// finally returns the final expression with the correct result + pub fn call( + &self, + parser: &mut Parser, + ctx: &mut Context, + body: &mut Block, + args: &mut [Handle], + meta: SourceMetadata, + ) -> Result> { + match *self { + MacroCall::Sampler => { + ctx.samplers.insert(args[0], args[1]); + Ok(args[0]) + } + MacroCall::SamplerShadow => { + sampled_to_depth(&mut parser.module, ctx, args[0], meta, &mut parser.errors)?; + parser.invalidate_expression(ctx, args[0], meta)?; + ctx.samplers.insert(args[0], args[1]); + Ok(args[0]) + } + MacroCall::Texture | MacroCall::TextureLod | MacroCall::TextureGrad => { + let comps = parser.coordinate_components(ctx, args[0], args[1], meta, body)?; + let level = match *self { + MacroCall::Texture => args + .get(2) + .copied() + .map_or(SampleLevel::Auto, SampleLevel::Bias), + MacroCall::TextureLod => SampleLevel::Exact(args[2]), + MacroCall::TextureGrad => SampleLevel::Gradient { + x: args[2], + y: args[3], + }, + _ => unreachable!(), + }; + texture_call(ctx, args[0], level, comps, body, meta) + } + MacroCall::TextureProj => { + let level = args + .get(2) + .copied() + .map_or(SampleLevel::Auto, SampleLevel::Bias); + let size = match *parser.resolve_type(ctx, args[1], meta)? { + TypeInner::Vector { size, .. } => size, + _ => { + return Err(Error { + kind: ErrorKind::SemanticError("Bad call to textureProj".into()), + meta, + }) + } + }; + let base = args[1]; + let mut right = ctx.add_expression( + Expression::AccessIndex { + base, + index: size as u32 - 1, + }, + SourceMetadata::none(), + body, + ); + let left = if let VectorSize::Bi = size { + ctx.add_expression( + Expression::AccessIndex { base, index: 0 }, + SourceMetadata::none(), + body, + ) + } else { + let size = match size { + VectorSize::Tri => VectorSize::Bi, + _ => VectorSize::Tri, + }; + right = ctx.add_expression( + Expression::Splat { size, value: right }, + SourceMetadata::none(), + body, + ); + ctx.vector_resize(size, base, SourceMetadata::none(), body) + }; + let coords = ctx.add_expression( + Expression::Binary { + op: BinaryOperator::Divide, + left, + right, + }, + SourceMetadata::none(), + body, + ); + let comps = parser.coordinate_components(ctx, args[0], coords, meta, body)?; + texture_call(ctx, args[0], level, comps, body, meta) + } + MacroCall::TextureSize => Ok(ctx.add_expression( + Expression::ImageQuery { + image: args[0], + query: ImageQuery::Size { + level: args.get(1).copied(), + }, + }, + SourceMetadata::none(), + body, + )), + MacroCall::TexelFetch => { + let comps = parser.coordinate_components(ctx, args[0], args[1], meta, body)?; + Ok(ctx.add_expression( + Expression::ImageLoad { + image: args[0], + coordinate: comps.coordinate, + array_index: comps.array_index, + index: Some(args[2]), + }, + SourceMetadata::none(), + body, + )) + } + MacroCall::MathFunction(fun) => Ok(ctx.add_expression( + Expression::Math { + fun, + arg: args[0], + arg1: args.get(1).copied(), + arg2: args.get(2).copied(), + }, + SourceMetadata::none(), + body, + )), + MacroCall::Relational(fun) => Ok(ctx.add_expression( + Expression::Relational { + fun, + argument: args[0], + }, + SourceMetadata::none(), + body, + )), + MacroCall::Binary(op) => Ok(ctx.add_expression( + Expression::Binary { + op, + left: args[0], + right: args[1], + }, + SourceMetadata::none(), + body, + )), + MacroCall::Mod(size) => { + ctx.implicit_splat(parser, &mut args[1], meta, size)?; + + Ok(ctx.add_expression( + Expression::Binary { + op: BinaryOperator::Modulo, + left: args[0], + right: args[1], + }, + SourceMetadata::none(), + body, + )) + } + MacroCall::Splatted(fun, size, i) => { + ctx.implicit_splat(parser, &mut args[i], meta, size)?; + + Ok(ctx.add_expression( + Expression::Math { + fun, + arg: args[0], + arg1: args.get(1).copied(), + arg2: args.get(2).copied(), + }, + SourceMetadata::none(), + body, + )) + } + MacroCall::MixBoolean => Ok(ctx.add_expression( + Expression::Select { + condition: args[2], + accept: args[1], + reject: args[0], + }, + SourceMetadata::none(), + body, + )), + MacroCall::Clamp(size) => { + ctx.implicit_splat(parser, &mut args[1], meta, size)?; + ctx.implicit_splat(parser, &mut args[2], meta, size)?; + + Ok(ctx.add_expression( + Expression::Math { + fun: MathFunction::Clamp, + arg: args[0], + arg1: args.get(1).copied(), + arg2: args.get(2).copied(), + }, + SourceMetadata::none(), + body, + )) + } + } + } +} + +fn texture_call( + ctx: &mut Context, + image: Handle, + level: SampleLevel, + comps: CoordComponents, + body: &mut Block, + meta: SourceMetadata, +) -> Result> { + if let Some(sampler) = ctx.samplers.get(&image).copied() { + Ok(ctx.add_expression( + Expression::ImageSample { + image, + sampler, + coordinate: comps.coordinate, + array_index: comps.array_index, + offset: None, + level, + depth_ref: comps.depth_ref, + }, + meta, + body, + )) + } else { + Err(Error { + kind: ErrorKind::SemanticError("Bad call".into()), + meta, + }) + } +} + +/// Helper struct for texture calls with the separate components from the vector argument +/// +/// Obtained by calling [`coordinate_components`](Parser::coordinate_components) +struct CoordComponents { + coordinate: Handle, + depth_ref: Option>, + array_index: Option>, +} + +impl Parser { + /// Helper function for texture calls, splits the vector argument into it's components + fn coordinate_components( + &mut self, + ctx: &mut Context, + image: Handle, + coord: Handle, + meta: SourceMetadata, + body: &mut Block, + ) -> Result { + if let TypeInner::Image { + dim, + arrayed, + class, + } = *self.resolve_type(ctx, image, meta)? + { + let image_size = match dim { + ImageDimension::D1 => None, + ImageDimension::D2 => Some(VectorSize::Bi), + ImageDimension::D3 => Some(VectorSize::Tri), + ImageDimension::Cube => Some(VectorSize::Tri), + }; + let coord_size = match *self.resolve_type(ctx, coord, meta)? { + TypeInner::Vector { size, .. } => Some(size), + _ => None, + }; + let shadow = match class { + ImageClass::Depth { .. } => true, + _ => false, + }; + + let coordinate = match (image_size, coord_size) { + (Some(size), Some(coord_s)) if size != coord_s => { + ctx.vector_resize(size, coord, SourceMetadata::none(), body) + } + (None, Some(_)) => ctx.add_expression( + Expression::AccessIndex { + base: coord, + index: 0, + }, + SourceMetadata::none(), + body, + ), + _ => coord, + }; + let array_index = match arrayed { + true => { + let index = match shadow { + true => image_size.map_or(0, |s| s as u32 - 1), + false => image_size.map_or(0, |s| s as u32), + }; + + Some(ctx.add_expression( + Expression::AccessIndex { base: coord, index }, + SourceMetadata::none(), + body, + )) + } + _ => None, + }; + let depth_ref = match shadow { + true => { + let index = image_size.map_or(0, |s| s as u32); + + Some(ctx.add_expression( + Expression::AccessIndex { base: coord, index }, + SourceMetadata::none(), + body, + )) + } + false => None, + }; + + Ok(CoordComponents { + coordinate, + depth_ref, + array_index, + }) + } else { + self.errors.push(Error { + kind: ErrorKind::SemanticError("Type is not an image".into()), + meta, + }); + + Ok(CoordComponents { + coordinate: coord, + depth_ref: None, + array_index: None, + }) + } + } +} + +/// Helper function to cast a expression holding a sampled image to a +/// depth image. +pub fn sampled_to_depth( + module: &mut Module, + ctx: &mut Context, + image: Handle, + meta: SourceMetadata, + errors: &mut Vec, +) -> Result<()> { + let ty = match ctx[image] { + Expression::GlobalVariable(handle) => &mut module.global_variables.get_mut(handle).ty, + Expression::FunctionArgument(i) => { + ctx.parameters_info[i as usize].depth = true; + &mut ctx.arguments[i as usize].ty + } + _ => { + return Err(Error { + kind: ErrorKind::SemanticError("Not a valid texture expression".into()), + meta, + }) + } + }; + match module.types[*ty].inner { + TypeInner::Image { + class, + dim, + arrayed, + } => match class { + ImageClass::Sampled { multi, .. } => { + *ty = module.types.fetch_or_append( + Type { + name: None, + inner: TypeInner::Image { + dim, + arrayed, + class: ImageClass::Depth { multi }, + }, + }, + Span::Unknown, + ) + } + ImageClass::Depth { .. } => {} + _ => errors.push(Error { + kind: ErrorKind::SemanticError("Not a texture".into()), + meta, + }), + }, + _ => errors.push(Error { + kind: ErrorKind::SemanticError("Not a texture".into()), + meta, + }), + }; + + Ok(()) +} diff --git a/src/front/glsl/context.rs b/src/front/glsl/context.rs index 1b8d7835c1..57787463c8 100644 --- a/src/front/glsl/context.rs +++ b/src/front/glsl/context.rs @@ -804,7 +804,7 @@ impl Context { ) -> Result> { Ok(self .expr_scalar_components(parser, expr, meta)? - .and_then(|(kind, _)| type_power(kind))) + .and_then(|(kind, width)| type_power(kind, width))) } pub fn implicit_conversion( @@ -815,9 +815,10 @@ impl Context { kind: ScalarKind, width: crate::Bytes, ) -> Result<()> { - if let (Some(tgt_power), Some(expr_power)) = - (type_power(kind), self.expr_power(parser, *expr, meta)?) - { + if let (Some(tgt_power), Some(expr_power)) = ( + type_power(kind, width), + self.expr_power(parser, *expr, meta)?, + ) { if tgt_power > expr_power { *expr = self.expressions.append( Expression::As { @@ -848,8 +849,9 @@ impl Context { Some((left_power, left_width, left_kind)), Some((right_power, right_width, right_kind)), ) = ( - left_components.and_then(|(kind, width)| Some((type_power(kind)?, width, kind))), - right_components.and_then(|(kind, width)| Some((type_power(kind)?, width, kind))), + left_components.and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))), + right_components + .and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))), ) { match left_power.cmp(&right_power) { std::cmp::Ordering::Less => { @@ -882,7 +884,6 @@ impl Context { pub fn implicit_splat( &mut self, parser: &mut Parser, - expr: &mut Handle, meta: SourceMetadata, vector_size: Option, diff --git a/src/front/glsl/error.rs b/src/front/glsl/error.rs index 3bd0c8af26..0a3c752987 100644 --- a/src/front/glsl/error.rs +++ b/src/front/glsl/error.rs @@ -124,22 +124,3 @@ pub struct Error { /// Holds information about the range of the source code where the error happened. pub meta: SourceMetadata, } - -impl Error { - pub(crate) fn wrong_function_args( - name: String, - expected: usize, - got: usize, - meta: SourceMetadata, - ) -> Self { - let msg = format!( - "Function \"{}\" expects {} arguments, got {}", - name, expected, got - ); - - Error { - kind: ErrorKind::SemanticError(msg.into()), - meta, - } - } -} diff --git a/src/front/glsl/functions.rs b/src/front/glsl/functions.rs index 8d5a1b780b..7c3444bfdd 100644 --- a/src/front/glsl/functions.rs +++ b/src/front/glsl/functions.rs @@ -1,27 +1,18 @@ use super::{ ast::*, + builtins::sampled_to_depth, context::{Context, StmtContext}, error::{Error, ErrorKind}, - types::{scalar_components, type_power}, + types::scalar_components, Parser, Result, SourceMetadata, }; use crate::{ - proc::ensure_block_returns, Arena, BinaryOperator, Block, Constant, ConstantInner, EntryPoint, - Expression, FastHashMap, Function, FunctionArgument, FunctionResult, Handle, ImageClass, - ImageDimension, ImageQuery, LocalVariable, MathFunction, Module, RelationalFunction, - SampleLevel, ScalarKind, ScalarValue, Statement, StructMember, Type, TypeInner, VectorSize, + front::glsl::types::type_power, proc::ensure_block_returns, Arena, Block, Constant, + ConstantInner, EntryPoint, Expression, FastHashMap, Function, FunctionArgument, FunctionResult, + Handle, LocalVariable, ScalarKind, ScalarValue, Span, Statement, StructMember, Type, TypeInner, }; use std::iter; -/// Helper struct for texture calls with the separate components from the vector argument -/// -/// Obtained by calling [`coordinate_components`](Parser::coordinate_components) -struct CoordComponents { - coordinate: Handle, - depth_ref: Option>, - array_index: Option>, -} - impl Parser { fn add_constant_value( &mut self, @@ -359,729 +350,266 @@ impl Parser { stmt: &StmtContext, body: &mut Block, name: String, - mut args: Vec<(Handle, SourceMetadata)>, + args: Vec<(Handle, SourceMetadata)>, raw_args: &[Handle], meta: SourceMetadata, ) -> Result>> { - match name.as_str() { - "sampler1D" | "sampler1DArray" | "sampler2D" | "sampler2DArray" | "sampler2DMS" - | "sampler2DMSArray" | "sampler3D" | "samplerCube" | "samplerCubeArray" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } - ctx.samplers.insert(args[0].0, args[1].0); - Ok(Some(args[0].0)) - } - "sampler1DShadow" - | "sampler1DArrayShadow" - | "sampler2DShadow" - | "sampler2DArrayShadow" - | "samplerCubeShadow" - | "samplerCubeArrayShadow" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } - sampled_to_depth(&mut self.module, ctx, args[0], &mut self.errors)?; - self.invalidate_expression(ctx, args[0].0, args[0].1)?; - ctx.samplers.insert(args[0].0, args[1].0); - Ok(Some(args[0].0)) - } - "texture" => { - if !(2..=3).contains(&args.len()) { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } - let arg_1 = &mut args[1]; - ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?; - if let Some(&mut (ref mut expr, meta)) = args.get_mut(2) { - ctx.implicit_conversion(self, expr, meta, ScalarKind::Float, 4)?; - } - let comps = self.coordinate_components(ctx, args[0], args[1], body)?; - if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(Some( - ctx.add_expression( - Expression::ImageSample { - image: args[0].0, - sampler, - coordinate: comps.coordinate, - array_index: comps.array_index, - offset: None, - level: args.get(2).map_or(SampleLevel::Auto, |&(expr, _)| { - SampleLevel::Bias(expr) - }), - depth_ref: comps.depth_ref, - }, - meta, - body, - ), - )) - } else { - Err(Error { - kind: ErrorKind::SemanticError("Bad call to texture".into()), - meta, - }) - } - } - "textureLod" => { - if args.len() != 3 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); - } - let arg_1 = &mut args[1]; - ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?; - let arg_2 = &mut args[2]; - ctx.implicit_conversion(self, &mut arg_2.0, arg_2.1, ScalarKind::Float, 4)?; - let comps = self.coordinate_components(ctx, args[0], args[1], body)?; - if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(Some(ctx.add_expression( - Expression::ImageSample { - image: args[0].0, - sampler, - coordinate: comps.coordinate, - array_index: comps.array_index, - offset: None, - level: SampleLevel::Exact(args[2].0), - depth_ref: comps.depth_ref, - }, - meta, - body, - ))) - } else { - Err(Error { - kind: ErrorKind::SemanticError("Bad call to textureLod".into()), - meta, - }) - } - } - "textureProj" => { - if !(2..=3).contains(&args.len()) { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } - let arg_1 = &mut args[1]; - ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?; - if let Some(&mut (ref mut expr, meta)) = args.get_mut(2) { - ctx.implicit_conversion(self, expr, meta, ScalarKind::Float, 4)?; - } - let level = args - .get(2) - .map_or(SampleLevel::Auto, |&(expr, _)| SampleLevel::Bias(expr)); - let size = match *self.resolve_type(ctx, args[1].0, args[1].1)? { - TypeInner::Vector { size, .. } => size, - _ => { - return Err(Error { - kind: ErrorKind::SemanticError("Bad call to textureProj".into()), - meta, - }) - } - }; - let (base, base_meta) = args[1]; - let mut right = ctx.add_expression( - Expression::AccessIndex { - base, - index: size as u32 - 1, - }, - meta, - body, - ); - let left = if let VectorSize::Bi = size { - ctx.add_expression(Expression::AccessIndex { base, index: 0 }, meta, body) - } else { - let size = match size { - VectorSize::Tri => VectorSize::Bi, - _ => VectorSize::Tri, - }; - right = - ctx.add_expression(Expression::Splat { size, value: right }, meta, body); - ctx.vector_resize(size, base, meta, body) - }; - let coords = ctx.add_expression( - Expression::Binary { - op: BinaryOperator::Divide, - left, - right, - }, - meta, - body, - ); - let comps = self.coordinate_components(ctx, args[0], (coords, base_meta), body)?; - if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(Some(ctx.add_expression( - Expression::ImageSample { - image: args[0].0, - sampler, - coordinate: comps.coordinate, - array_index: comps.array_index, - offset: None, - level, - depth_ref: comps.depth_ref, - }, - meta, - body, - ))) - } else { - Err(Error { - kind: ErrorKind::SemanticError("Bad call to textureProj".into()), - meta, - }) - } - } - "textureGrad" => { - if args.len() != 4 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); - } - let arg_1 = &mut args[1]; - ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Float, 4)?; - let arg_2 = &mut args[2]; - ctx.implicit_conversion(self, &mut arg_2.0, arg_2.1, ScalarKind::Float, 4)?; - let arg_3 = &mut args[3]; - ctx.implicit_conversion(self, &mut arg_3.0, arg_3.1, ScalarKind::Float, 4)?; - let comps = self.coordinate_components(ctx, args[0], args[1], body)?; - if let Some(sampler) = ctx.samplers.get(&args[0].0).copied() { - Ok(Some(ctx.add_expression( - Expression::ImageSample { - image: args[0].0, - sampler, - coordinate: comps.coordinate, - array_index: comps.array_index, - offset: None, - level: SampleLevel::Gradient { - x: args[2].0, - y: args[3].0, - }, - depth_ref: comps.depth_ref, - }, - meta, - body, - ))) - } else { - Err(Error { - kind: ErrorKind::SemanticError("Bad call to textureGrad".into()), - meta, - }) - } - } - "textureSize" => { - if !(1..=2).contains(&args.len()) { - return Err(Error::wrong_function_args(name, 1, args.len(), meta)); - } - if let Some(&mut (ref mut expr, meta)) = args.get_mut(1) { - ctx.implicit_conversion(self, expr, meta, ScalarKind::Sint, 4)?; - } - Ok(Some(ctx.add_expression( - Expression::ImageQuery { - image: args[0].0, - query: ImageQuery::Size { - level: args.get(1).map(|e| e.0), - }, - }, - meta, - body, - ))) - } - "texelFetch" => { - if args.len() != 3 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); - } - let arg_1 = &mut args[1]; - ctx.implicit_conversion(self, &mut arg_1.0, arg_1.1, ScalarKind::Sint, 4)?; - let arg_2 = &mut args[2]; - ctx.implicit_conversion(self, &mut arg_2.0, arg_2.1, ScalarKind::Sint, 4)?; - let comps = self.coordinate_components(ctx, args[0], args[1], body)?; - if ctx.samplers.get(&args[0].0).is_some() && comps.depth_ref.is_none() { - Ok(Some(ctx.add_expression( - Expression::ImageLoad { - image: args[0].0, - coordinate: comps.coordinate, - array_index: comps.array_index, - index: Some(args[2].0), - }, - meta, - body, - ))) - } else { - Err(Error { - kind: ErrorKind::SemanticError("Bad call to texelFetch".into()), - meta, - }) - } - } - "ceil" | "round" | "floor" | "fract" | "trunc" | "sin" | "abs" | "sqrt" - | "inversesqrt" | "exp" | "exp2" | "sign" | "transpose" | "inverse" | "normalize" - | "sinh" | "cos" | "cosh" | "tan" | "tanh" | "acos" | "asin" | "log" | "log2" - | "length" | "determinant" | "bitCount" | "bitfieldReverse" => { - if args.len() != 1 { - return Err(Error::wrong_function_args(name, 1, args.len(), meta)); - } - Ok(Some(ctx.add_expression( - Expression::Math { - fun: match name.as_str() { - "ceil" => MathFunction::Ceil, - "round" => MathFunction::Round, - "floor" => MathFunction::Floor, - "fract" => MathFunction::Fract, - "trunc" => MathFunction::Trunc, - "sin" => MathFunction::Sin, - "abs" => MathFunction::Abs, - "sqrt" => MathFunction::Sqrt, - "inversesqrt" => MathFunction::InverseSqrt, - "exp" => MathFunction::Exp, - "exp2" => MathFunction::Exp2, - "sign" => MathFunction::Sign, - "transpose" => MathFunction::Transpose, - "inverse" => MathFunction::Inverse, - "normalize" => MathFunction::Normalize, - "sinh" => MathFunction::Sinh, - "cos" => MathFunction::Cos, - "cosh" => MathFunction::Cosh, - "tan" => MathFunction::Tan, - "tanh" => MathFunction::Tanh, - "acos" => MathFunction::Acos, - "asin" => MathFunction::Asin, - "log" => MathFunction::Log, - "log2" => MathFunction::Log2, - "length" => MathFunction::Length, - "determinant" => MathFunction::Determinant, - "bitCount" => MathFunction::CountOneBits, - "bitfieldReverse" => MathFunction::ReverseBits, - _ => unreachable!(), - }, - arg: args[0].0, - arg1: None, - arg2: None, - }, - meta, - body, - ))) - } - "atan" => { - let expr = match args.len() { - 1 => Expression::Math { - fun: MathFunction::Atan, - arg: args[0].0, - arg1: None, - arg2: None, - }, - 2 => Expression::Math { - fun: MathFunction::Atan2, - arg: args[0].0, - arg1: Some(args[1].0), - arg2: None, - }, - _ => return Err(Error::wrong_function_args(name, 2, args.len(), meta)), - }; - Ok(Some(ctx.add_expression(expr, meta, body))) - } - "mod" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } + // 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 (mut left, left_meta) = args[0]; - let (mut right, right_meta) = args[1]; + let declarations = self.lookup_function.get(&name).ok_or_else(|| Error { + kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()), + meta, + })?; + + // Helper enum containing the type of conversion need for a call + #[derive(PartialEq, Eq, Clone, Copy, Debug)] + enum Conversion { + // No conversion needed + Exact, + // Float to double conversion needed + FloatToDouble, + // Int or uint to float conversion needed + IntToFloat, + // Int or uint to double conversion needed + IntToDouble, + // Other type of conversion needed + Other, + // No conversion was yet registered + None, + } - ctx.binary_implicit_conversion(self, &mut left, left_meta, &mut right, right_meta)?; + let mut maybe_decl = None; + let mut old_conversions = vec![Conversion::None; args.len()]; + let mut ambiguous = false; - Ok(Some(ctx.add_expression( - Expression::Binary { - op: BinaryOperator::Modulo, - left, - right, - }, - meta, - body, - ))) + 'outer: for decl in declarations { + if args.len() != decl.parameters.len() { + continue; } - "min" | "max" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } - - let (mut arg0, arg0_meta) = args[0]; - let (mut arg1, arg1_meta) = args[1]; - ctx.binary_implicit_conversion(self, &mut arg0, arg0_meta, &mut arg1, arg1_meta)?; - - if let TypeInner::Vector { size, .. } = *self.resolve_type(ctx, arg0, arg0_meta)? { - ctx.implicit_splat(self, &mut arg1, arg1_meta, Some(size))?; - } - if let TypeInner::Vector { size, .. } = *self.resolve_type(ctx, arg1, arg1_meta)? { - ctx.implicit_splat(self, &mut arg0, arg0_meta, Some(size))?; + let mut exact = true; + // State of the selection + // If None we still don't know what is the best declaration + // If Some(true) the new declaration is better + // If Some(false) the old declaration is better + let mut superior = None; + let mut new_conversions = vec![Conversion::None; args.len()]; + + for ((i, decl_arg), call_arg) in decl.parameters.iter().enumerate().zip(args.iter()) { + use ScalarKind::*; + + if decl.parameters_info[i].depth { + sampled_to_depth( + &mut self.module, + ctx, + call_arg.0, + call_arg.1, + &mut self.errors, + )?; + self.invalidate_expression(ctx, call_arg.0, call_arg.1)? } - Ok(Some(ctx.add_expression( - Expression::Math { - fun: match name.as_str() { - "min" => MathFunction::Min, - "max" => MathFunction::Max, - _ => unreachable!(), - }, - arg: arg0, - arg1: Some(arg1), - arg2: None, - }, - meta, - body, - ))) - } - "pow" | "dot" | "reflect" | "cross" | "outerProduct" | "distance" | "step" | "modf" - | "frexp" | "ldexp" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); - } + let decl_inner = &self.module.types[*decl_arg].inner; + let call_inner = self.resolve_type(ctx, call_arg.0, call_arg.1)?; - let (mut arg0, arg0_meta) = args[0]; - let (mut arg1, arg1_meta) = args[1]; - - ctx.binary_implicit_conversion(self, &mut arg0, arg0_meta, &mut arg1, arg1_meta)?; - - Ok(Some(ctx.add_expression( - Expression::Math { - fun: match name.as_str() { - "pow" => MathFunction::Pow, - "dot" => MathFunction::Dot, - "reflect" => MathFunction::Reflect, - "cross" => MathFunction::Cross, - "outerProduct" => MathFunction::Outer, - "distance" => MathFunction::Distance, - "step" => MathFunction::Step, - "modf" => MathFunction::Modf, - "frexp" => MathFunction::Frexp, - "ldexp" => MathFunction::Ldexp, - _ => unreachable!(), - }, - arg: arg0, - arg1: Some(arg1), - arg2: None, - }, - meta, - body, - ))) - } - "mix" => { - if args.len() != 3 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); + if decl_inner == call_inner { + new_conversions[i] = Conversion::Exact; + continue; } - let (mut arg, arg_meta) = args[0]; - let (mut arg1, arg1_meta) = args[1]; - let (mut selector, selector_meta) = args[2]; - - ctx.binary_implicit_conversion(self, &mut arg, arg_meta, &mut arg1, arg1_meta)?; - ctx.binary_implicit_conversion( - self, - &mut arg, - arg_meta, - &mut selector, - selector_meta, - )?; - ctx.binary_implicit_conversion( - self, - &mut arg1, - arg1_meta, - &mut selector, - selector_meta, - )?; - - let is_vector = match *self.resolve_type(ctx, selector, selector_meta)? { - TypeInner::Vector { .. } => true, - _ => false, - }; - match *self.resolve_type(ctx, args[0].0, args[0].1)? { - TypeInner::Vector { size, .. } if !is_vector => { - selector = ctx.add_expression( - Expression::Splat { - size, - value: selector, - }, - meta, - body, - ) - } - _ => {} - }; + exact = false; - let expr = match self - .resolve_type(ctx, selector, selector_meta)? - .scalar_kind() + let (decl_kind, decl_width, call_kind, call_width) = match (decl_inner, call_inner) { - // When the selector is a boolean vector the result is - // calculated per component, for each component of the - // selector if it's false the respective component from the - // first argument is selected, if it's true the respective - // component from the second argument is selected - // - // Note(jcapucho): yes, it's inverted in comparison with the - // IR and SPIR-V and yes I spent a full debugging a shader - // because of this weird behavior - Some(ScalarKind::Bool) => Expression::Select { - condition: selector, - accept: arg1, - reject: arg, - }, - _ => Expression::Math { - fun: MathFunction::Mix, - arg, - arg1: Some(arg1), - arg2: Some(selector), - }, + ( + &TypeInner::Scalar { + kind: decl_kind, + width: decl_width, + }, + &TypeInner::Scalar { + kind: call_kind, + width: call_width, + }, + ) => (decl_kind, decl_width, call_kind, call_width), + ( + &TypeInner::Vector { + kind: decl_kind, + size: decl_size, + width: decl_width, + }, + &TypeInner::Vector { + kind: call_kind, + size: call_size, + width: call_width, + }, + ) if decl_size == call_size => (decl_kind, decl_width, call_kind, call_width), + ( + &TypeInner::Matrix { + rows: decl_rows, + columns: decl_columns, + width: decl_width, + }, + &TypeInner::Matrix { + rows: call_rows, + columns: call_columns, + width: call_width, + }, + ) if decl_columns == call_columns && decl_rows == call_rows => { + (Float, decl_width, Float, call_width) + } + _ => continue 'outer, }; - Ok(Some(ctx.add_expression(expr, meta, body))) - } - "clamp" => { - if args.len() != 3 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); + if type_power(decl_kind, decl_width) < type_power(call_kind, call_width) { + continue 'outer; } - let (mut arg0, arg0_meta) = args[0]; - let (mut arg1, arg1_meta) = args[1]; - let (mut arg2, arg2_meta) = args[2]; - - let vector_size = match *(self.resolve_type(ctx, arg0, arg0_meta)?) { - TypeInner::Vector { size, .. } => Some(size), - _ => None, + let conversion = match ((decl_kind, decl_width), (call_kind, call_width)) { + ((Float, 8), (Float, 4)) => Conversion::FloatToDouble, + ((Float, 4), (Sint, _)) | ((Float, 4), (Uint, _)) => Conversion::IntToFloat, + ((Float, 8), (Sint, _)) | ((Float, 8), (Uint, _)) => Conversion::IntToDouble, + _ => Conversion::Other, }; - ctx.binary_implicit_conversion(self, &mut arg0, arg0_meta, &mut arg1, arg1_meta)?; - ctx.binary_implicit_conversion(self, &mut arg1, arg1_meta, &mut arg2, arg2_meta)?; - ctx.binary_implicit_conversion(self, &mut arg2, arg2_meta, &mut arg0, arg0_meta)?; - - ctx.implicit_splat(self, &mut arg1, arg1_meta, vector_size)?; - ctx.implicit_splat(self, &mut arg2, arg2_meta, vector_size)?; + // true - New declaration argument has a better conversion + // false - Old declaration argument has a better conversion + let best_arg = match (conversion, old_conversions[i]) { + (_, Conversion::Exact) => false, + (Conversion::FloatToDouble, _) + | (_, Conversion::None) + | (Conversion::IntToFloat, Conversion::IntToDouble) => true, + (_, Conversion::FloatToDouble) + | (Conversion::IntToDouble, Conversion::IntToFloat) => false, + _ => continue, + }; - Ok(Some(ctx.add_expression( - Expression::Math { - fun: MathFunction::Clamp, - arg: arg0, - arg1: Some(arg1), - arg2: Some(arg2), + match best_arg { + true => match superior { + Some(false) => ambiguous = true, + _ => { + superior = Some(true); + new_conversions[i] = conversion + } }, - meta, - body, - ))) - } - "faceforward" | "refract" | "fma" | "smoothstep" => { - if args.len() != 3 { - return Err(Error::wrong_function_args(name, 3, args.len(), meta)); - } - Ok(Some(ctx.add_expression( - Expression::Math { - fun: match name.as_str() { - "faceforward" => MathFunction::FaceForward, - "refract" => MathFunction::Refract, - "fma" => MathFunction::Fma, - "smoothstep" => MathFunction::SmoothStep, - _ => unreachable!(), - }, - arg: args[0].0, - arg1: Some(args[1].0), - arg2: Some(args[2].0), + false => match superior { + Some(true) => ambiguous = true, + _ => superior = Some(false), }, - meta, - body, - ))) - } - "lessThan" | "greaterThan" | "lessThanEqual" | "greaterThanEqual" | "equal" - | "notEqual" => { - if args.len() != 2 { - return Err(Error::wrong_function_args(name, 2, args.len(), meta)); } - Ok(Some(ctx.add_expression( - Expression::Binary { - op: match name.as_str() { - "lessThan" => BinaryOperator::Less, - "greaterThan" => BinaryOperator::Greater, - "lessThanEqual" => BinaryOperator::LessEqual, - "greaterThanEqual" => BinaryOperator::GreaterEqual, - "equal" => BinaryOperator::Equal, - "notEqual" => BinaryOperator::NotEqual, - _ => unreachable!(), - }, - left: args[0].0, - right: args[1].0, - }, - meta, - body, - ))) } - "isinf" | "isnan" | "all" | "any" => { - let fun = match name.as_str() { - "isinf" => RelationalFunction::IsInf, - "isnan" => RelationalFunction::IsNan, - "all" => RelationalFunction::All, - "any" => RelationalFunction::Any, - _ => unreachable!(), - }; - Ok(Some( - self.parse_relational_fun(ctx, body, name, &args, fun, meta)?, - )) + if exact { + maybe_decl = Some(decl); + ambiguous = false; + break; } - _ => { - let declarations = self.lookup_function.get(&name).ok_or_else(|| Error { - kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()), - meta, - })?; - let mut maybe_decl = None; - let mut ambiguous = false; - - 'outer: for decl in declarations { - if args.len() != decl.parameters.len() { - continue; - } - - let mut exact = true; - - for ((i, decl_arg), call_arg) in - decl.parameters.iter().enumerate().zip(args.iter()) - { - if decl.parameters_info[i].depth { - sampled_to_depth(&mut self.module, ctx, *call_arg, &mut self.errors)?; - self.invalidate_expression(ctx, call_arg.0, call_arg.1)? - } - - let decl_inner = &self.module.types[*decl_arg].inner; - let call_inner = self.resolve_type(ctx, call_arg.0, call_arg.1)?; - - if decl_inner == call_inner { - continue; - } - - exact = false; + match superior { + // New declaration is better keep it + Some(true) => { + maybe_decl = Some(decl); + // Replace the conversions + old_conversions = new_conversions; + } + // Old declaration is better do nothing + Some(false) => {} + // No declaration was better than the other this can be caused + // when + None => { + ambiguous = true; + // Assign the new declaration to make sure we always have + // one to make error reporting happy + maybe_decl = Some(decl); + } + } + } - let (decl_kind, call_kind) = match (decl_inner, call_inner) { - ( - &TypeInner::Scalar { - kind: decl_kind, .. - }, - &TypeInner::Scalar { - kind: call_kind, .. - }, - ) => (decl_kind, call_kind), - ( - &TypeInner::Vector { - kind: decl_kind, - size: decl_size, - .. - }, - &TypeInner::Vector { - kind: call_kind, - size: call_size, - .. - }, - ) if decl_size == call_size => (decl_kind, call_kind), - ( - &TypeInner::Matrix { - rows: decl_rows, - columns: decl_columns, - .. - }, - &TypeInner::Matrix { - rows: call_rows, - columns: call_columns, - .. - }, - ) if decl_columns == call_columns && decl_rows == call_rows => { - (ScalarKind::Float, ScalarKind::Float) - } - _ => continue 'outer, - }; + if ambiguous { + self.errors.push(Error { + kind: ErrorKind::SemanticError( + format!("Ambiguous best function for '{}'", name).into(), + ), + meta, + }) + } - match (type_power(decl_kind), type_power(call_kind)) { - (Some(decl_power), Some(call_power)) if decl_power > call_power => {} - _ => continue 'outer, - } - } + let decl = maybe_decl.ok_or_else(|| Error { + kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()), + meta, + })?; - if exact { - maybe_decl = Some(decl); - ambiguous = false; - break; - } else if maybe_decl.is_some() { - ambiguous = true; - } else { - maybe_decl = Some(decl) - } - } + let parameters_info = decl.parameters_info.clone(); + let parameters = decl.parameters.clone(); + let is_void = decl.void; + let kind = decl.kind; - if ambiguous { - self.errors.push(Error { - kind: ErrorKind::SemanticError( - format!("Ambiguous best function for '{}'", name).into(), - ), - meta, - }) - } - - let decl = maybe_decl.ok_or_else(|| Error { - kind: ErrorKind::SemanticError(format!("Unknown function '{}'", name).into()), - meta, - })?; - - let parameters_info = decl.parameters_info.clone(); - let parameters = decl.parameters.clone(); - let function = decl.handle; - let is_void = decl.void; - - let mut arguments = Vec::with_capacity(args.len()); - let mut proxy_writes = Vec::new(); - for (parameter_info, (expr, parameter)) in parameters_info - .iter() - .zip(raw_args.iter().zip(parameters.iter())) + let mut arguments = Vec::with_capacity(args.len()); + let mut proxy_writes = Vec::new(); + for (parameter_info, (expr, parameter)) in parameters_info + .iter() + .zip(raw_args.iter().zip(parameters.iter())) + { + let (mut handle, meta) = + ctx.lower_expect_inner(stmt, self, *expr, parameter_info.qualifier.is_lhs(), body)?; + + if let TypeInner::Vector { size, kind, width } = + *self.resolve_type(ctx, handle, meta)? + { + if parameter_info.qualifier.is_lhs() + && matches!(ctx[handle], Expression::Swizzle { .. }) { - let (mut handle, meta) = ctx.lower_expect_inner( - stmt, - self, - *expr, - parameter_info.qualifier.is_lhs(), + let ty = self.module.types.fetch_or_append( + Type { + name: None, + inner: TypeInner::Vector { size, kind, width }, + }, + Span::Unknown, + ); + let temp_var = ctx.locals.append( + LocalVariable { + name: None, + ty, + init: None, + }, + Span::Unknown, + ); + let temp_expr = ctx.add_expression( + Expression::LocalVariable(temp_var), + SourceMetadata::none(), body, - )?; - - if let TypeInner::Vector { size, kind, width } = - *self.resolve_type(ctx, handle, meta)? - { - if parameter_info.qualifier.is_lhs() - && matches!(ctx[handle], Expression::Swizzle { .. }) - { - let ty = self.module.types.fetch_or_append( - Type { - name: None, - inner: TypeInner::Vector { size, kind, width }, - }, - meta.as_span(), - ); - let temp_var = ctx.locals.append( - LocalVariable { - name: None, - ty, - init: None, - }, - meta.as_span(), - ); - let temp_expr = - ctx.add_expression(Expression::LocalVariable(temp_var), meta, body); + ); - body.push( - Statement::Store { - pointer: temp_expr, - value: handle, - }, - meta.as_span(), - ); + body.push( + Statement::Store { + pointer: temp_expr, + value: handle, + }, + Span::Unknown, + ); - arguments.push(temp_expr); - proxy_writes.push((*expr, temp_expr)); - continue; - } - } + arguments.push(temp_expr); + proxy_writes.push((*expr, temp_expr)); + continue; + } + } - let scalar_components = scalar_components(&self.module.types[*parameter].inner); - if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(self, &mut handle, meta, kind, width)?; - } + let scalar_components = scalar_components(&self.module.types[*parameter].inner); + if let Some((kind, width)) = scalar_components { + ctx.implicit_conversion(self, &mut handle, meta, kind, width)?; + } - arguments.push(handle) - } + arguments.push(handle) + } + match kind { + FunctionKind::Call(function) => { ctx.emit_flush(body); let result = if !is_void { @@ -1117,32 +645,12 @@ impl Parser { Ok(result) } + FunctionKind::Macro(builtin) => builtin + .call(self, ctx, body, arguments.as_mut_slice(), meta) + .map(Some), } } - pub(crate) fn parse_relational_fun( - &mut self, - ctx: &mut Context, - body: &mut Block, - name: String, - args: &[(Handle, SourceMetadata)], - fun: RelationalFunction, - meta: SourceMetadata, - ) -> Result> { - if args.len() != 1 { - return Err(Error::wrong_function_args(name, 1, args.len(), meta)); - } - - Ok(ctx.add_expression( - Expression::Relational { - fun, - argument: args[0].0, - }, - meta, - body, - )) - } - pub(crate) fn add_function( &mut self, ctx: Context, @@ -1151,6 +659,10 @@ impl Parser { mut body: Block, meta: SourceMetadata, ) { + if self.lookup_function.get(&name).is_none() { + self.inject_builtin(name.clone()); + } + ensure_block_returns(&mut body); let void = result.is_none(); @@ -1203,7 +715,13 @@ impl Parser { decl.defined = true; decl.parameters_info = parameters_info; - *self.module.functions.get_mut(decl.handle) = function; + match decl.kind { + FunctionKind::Call(handle) => *self.module.functions.get_mut(handle) = function, + FunctionKind::Macro(_) => { + let handle = module.functions.append(function, meta.as_span()); + decl.kind = FunctionKind::Call(handle) + } + } return; } @@ -1211,7 +729,7 @@ impl Parser { declarations.push(FunctionDeclaration { parameters, parameters_info, - handle, + kind: FunctionKind::Call(handle), defined: true, void, }); @@ -1224,6 +742,10 @@ impl Parser { result: Option, meta: SourceMetadata, ) { + if self.lookup_function.get(&name).is_none() { + self.inject_builtin(name.clone()); + } + let void = result.is_none(); let &mut Parser { @@ -1271,7 +793,7 @@ impl Parser { declarations.push(FunctionDeclaration { parameters, parameters_info, - handle, + kind: FunctionKind::Call(handle), defined: false, void, }); @@ -1399,149 +921,4 @@ impl Parser { }, }); } - - /// Helper function for texture calls, splits the vector argument into it's components - fn coordinate_components( - &mut self, - ctx: &mut Context, - (image, image_meta): (Handle, SourceMetadata), - (coord, coord_meta): (Handle, SourceMetadata), - body: &mut Block, - ) -> Result { - if let TypeInner::Image { - dim, - arrayed, - class, - } = *self.resolve_type(ctx, image, image_meta)? - { - let image_size = match dim { - ImageDimension::D1 => None, - ImageDimension::D2 => Some(VectorSize::Bi), - ImageDimension::D3 => Some(VectorSize::Tri), - ImageDimension::Cube => Some(VectorSize::Tri), - }; - let coord_size = match *self.resolve_type(ctx, coord, coord_meta)? { - TypeInner::Vector { size, .. } => Some(size), - _ => None, - }; - let shadow = match class { - ImageClass::Depth { .. } => true, - _ => false, - }; - - let coordinate = match (image_size, coord_size) { - (Some(size), Some(coord_s)) if size != coord_s => { - ctx.vector_resize(size, coord, coord_meta, body) - } - (None, Some(_)) => ctx.add_expression( - Expression::AccessIndex { - base: coord, - index: 0, - }, - coord_meta, - body, - ), - _ => coord, - }; - let array_index = match arrayed { - true => { - let index = match shadow { - true => image_size.map_or(0, |s| s as u32 - 1), - false => image_size.map_or(0, |s| s as u32), - }; - - Some(ctx.add_expression( - Expression::AccessIndex { base: coord, index }, - coord_meta, - body, - )) - } - _ => None, - }; - let depth_ref = match shadow { - true => { - let index = image_size.map_or(0, |s| s as u32); - - Some(ctx.add_expression( - Expression::AccessIndex { base: coord, index }, - coord_meta, - body, - )) - } - false => None, - }; - - Ok(CoordComponents { - coordinate, - depth_ref, - array_index, - }) - } else { - self.errors.push(Error { - kind: ErrorKind::SemanticError("Type is not an image".into()), - meta: image_meta, - }); - - Ok(CoordComponents { - coordinate: coord, - depth_ref: None, - array_index: None, - }) - } - } -} - -/// Helper function to cast a expression holding a sampled image to a -/// depth image. -fn sampled_to_depth( - module: &mut Module, - ctx: &mut Context, - (image, meta): (Handle, SourceMetadata), - errors: &mut Vec, -) -> Result<()> { - let ty = match ctx[image] { - Expression::GlobalVariable(handle) => &mut module.global_variables.get_mut(handle).ty, - Expression::FunctionArgument(i) => { - ctx.parameters_info[i as usize].depth = true; - &mut ctx.arguments[i as usize].ty - } - _ => { - return Err(Error { - kind: ErrorKind::SemanticError("Not a valid texture expression".into()), - meta, - }) - } - }; - match module.types[*ty].inner { - TypeInner::Image { - class, - dim, - arrayed, - } => match class { - ImageClass::Sampled { multi, .. } => { - *ty = module.types.fetch_or_append( - Type { - name: None, - inner: TypeInner::Image { - dim, - arrayed, - class: ImageClass::Depth { multi }, - }, - }, - module.types.get_span(*ty).clone(), - ) - } - ImageClass::Depth { .. } => {} - _ => errors.push(Error { - kind: ErrorKind::SemanticError("Not a texture".into()), - meta, - }), - }, - _ => errors.push(Error { - kind: ErrorKind::SemanticError("Not a texture".into()), - meta, - }), - }; - - Ok(()) } diff --git a/src/front/glsl/mod.rs b/src/front/glsl/mod.rs index 7f8fba66c4..29a062b3c4 100644 --- a/src/front/glsl/mod.rs +++ b/src/front/glsl/mod.rs @@ -15,6 +15,7 @@ use ast::{EntryArg, FunctionDeclaration, GlobalLookup}; use parser::ParsingContext; mod ast; +mod builtins; mod constants; mod context; mod error; diff --git a/src/front/glsl/parser.rs b/src/front/glsl/parser.rs index a43396df60..b62adcca0e 100644 --- a/src/front/glsl/parser.rs +++ b/src/front/glsl/parser.rs @@ -1,5 +1,5 @@ use super::{ - ast::{Profile, TypeQualifier}, + ast::{FunctionKind, Profile, TypeQualifier}, context::Context, error::ExpectedToken, error::{Error, ErrorKind}, @@ -140,10 +140,12 @@ impl<'source> ParsingContext<'source> { } match parser.lookup_function.get("main").and_then(|declarations| { - declarations - .iter() - .find(|decl| decl.defined && decl.parameters.is_empty()) - .map(|decl| decl.handle) + declarations.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 { diff --git a/src/front/glsl/parser/expressions.rs b/src/front/glsl/parser/expressions.rs index 02184e9bd8..175c451dce 100644 --- a/src/front/glsl/parser/expressions.rs +++ b/src/front/glsl/parser/expressions.rs @@ -297,7 +297,6 @@ impl<'source> ParsingContext<'source> { stmt: &mut StmtContext, body: &mut Block, ) -> Result> { - // TODO: prefix inc/dec Ok(match self.expect_peek(parser)?.value { TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => { let Token { value, meta } = self.bump(parser)?; diff --git a/src/front/glsl/types.rs b/src/front/glsl/types.rs index fe591f65b6..7901edcb96 100644 --- a/src/front/glsl/types.rs +++ b/src/front/glsl/types.rs @@ -2,8 +2,8 @@ use super::{ constants::ConstantSolver, context::Context, Error, ErrorKind, Parser, Result, SourceMetadata, }; use crate::{ - proc::ResolveContext, ArraySize, Constant, Expression, Handle, ImageClass, ImageDimension, - ScalarKind, Type, TypeInner, VectorSize, + proc::ResolveContext, ArraySize, Bytes, Constant, Expression, Handle, ImageClass, + ImageDimension, ScalarKind, Type, TypeInner, VectorSize, }; pub fn parse_type(type_name: &str) -> Option { @@ -159,7 +159,7 @@ pub fn parse_type(type_name: &str) -> Option { } } -pub fn scalar_components(ty: &TypeInner) -> Option<(ScalarKind, crate::Bytes)> { +pub fn scalar_components(ty: &TypeInner) -> Option<(ScalarKind, Bytes)> { match *ty { TypeInner::Scalar { kind, width } => Some((kind, width)), TypeInner::Vector { kind, width, .. } => Some((kind, width)), @@ -169,11 +169,12 @@ pub fn scalar_components(ty: &TypeInner) -> Option<(ScalarKind, crate::Bytes)> { } } -pub fn type_power(kind: ScalarKind) -> Option { +pub fn type_power(kind: ScalarKind, width: Bytes) -> Option { Some(match kind { ScalarKind::Sint => 0, ScalarKind::Uint => 1, - ScalarKind::Float => 2, + ScalarKind::Float if width == 4 => 2, + ScalarKind::Float => 3, ScalarKind::Bool => return None, }) } diff --git a/tests/out/wgsl/246-collatz-comp.wgsl b/tests/out/wgsl/246-collatz-comp.wgsl index a0ee765350..e052f4b486 100644 --- a/tests/out/wgsl/246-collatz-comp.wgsl +++ b/tests/out/wgsl/246-collatz-comp.wgsl @@ -19,25 +19,25 @@ fn collatz_iterations(n: u32) -> u32 { break; } { - let _e12: u32 = n1; - if (((_e12 % u32(2)) == u32(0))) { + let _e14: u32 = n1; + if (((f32(_e14) % f32(2)) == f32(0))) { { - let _e19: u32 = n1; - n1 = (_e19 / u32(2)); + let _e22: u32 = n1; + n1 = (_e22 / u32(2)); } } else { { - let _e24: u32 = n1; - n1 = ((u32(3) * _e24) + u32(1)); + let _e27: u32 = n1; + n1 = ((u32(3) * _e27) + u32(1)); } } - let _e30: u32 = i; - local = _e30; - i = (_e30 + 1u); + let _e33: u32 = i; + local = _e33; + i = (_e33 + 1u); } } - let _e35: u32 = i; - return _e35; + let _e38: u32 = i; + return _e38; } fn main1() { diff --git a/tests/out/wgsl/bevy-pbr-frag.wgsl b/tests/out/wgsl/bevy-pbr-frag.wgsl index ef33443868..8ff5b88233 100644 --- a/tests/out/wgsl/bevy-pbr-frag.wgsl +++ b/tests/out/wgsl/bevy-pbr-frag.wgsl @@ -127,13 +127,15 @@ fn getDistanceAttenuation(distanceSquare: f32, inverseRangeSquared: f32) -> f32 factor = (_e44 * _e45); let _e49: f32 = factor; let _e50: f32 = factor; - smoothFactor = clamp((1.0 - (_e49 * _e50)), 0.0, 1.0); - let _e57: f32 = smoothFactor; - let _e58: f32 = smoothFactor; - attenuation = (_e57 * _e58); - let _e61: f32 = attenuation; - let _e64: f32 = distanceSquare1; - return ((_e61 * 1.0) / max(_e64, 0.00009999999747378752)); + let _e56: f32 = factor; + let _e57: f32 = factor; + smoothFactor = clamp((1.0 - (_e56 * _e57)), 0.0, 1.0); + let _e64: f32 = smoothFactor; + let _e65: f32 = smoothFactor; + attenuation = (_e64 * _e65); + let _e68: f32 = attenuation; + let _e73: f32 = distanceSquare1; + return ((_e68 * 1.0) / max(_e73, 0.00009999999747378752)); } fn D_GGX(roughness: f32, NoH: f32, h: vec3) -> f32 { @@ -185,19 +187,29 @@ fn V_SmithGGXCorrelated(roughness2: f32, NoV: f32, NoL: f32) -> f32 { let _e53: f32 = NoV1; let _e56: f32 = NoV1; let _e58: f32 = a2_; - lambdaV = (_e50 * sqrt((((_e51 - (_e52 * _e53)) * _e56) + _e58))); - let _e63: f32 = NoV1; - let _e64: f32 = NoL1; - let _e65: f32 = a2_; - let _e66: f32 = NoL1; - let _e69: f32 = NoL1; - let _e71: f32 = a2_; - lambdaL = (_e63 * sqrt((((_e64 - (_e65 * _e66)) * _e69) + _e71))); - let _e77: f32 = lambdaV; - let _e78: f32 = lambdaL; - v = (0.5 / (_e77 + _e78)); - let _e82: f32 = v; - return _e82; + let _e60: f32 = NoV1; + let _e61: f32 = a2_; + let _e62: f32 = NoV1; + let _e65: f32 = NoV1; + let _e67: f32 = a2_; + lambdaV = (_e50 * sqrt((((_e60 - (_e61 * _e62)) * _e65) + _e67))); + let _e72: f32 = NoV1; + let _e73: f32 = NoL1; + let _e74: f32 = a2_; + let _e75: f32 = NoL1; + let _e78: f32 = NoL1; + let _e80: f32 = a2_; + let _e82: f32 = NoL1; + let _e83: f32 = a2_; + let _e84: f32 = NoL1; + let _e87: f32 = NoL1; + let _e89: f32 = a2_; + lambdaL = (_e72 * sqrt((((_e82 - (_e83 * _e84)) * _e87) + _e89))); + let _e95: f32 = lambdaV; + let _e96: f32 = lambdaL; + v = (0.5 / (_e95 + _e96)); + let _e100: f32 = v; + return _e100; } fn F_Schlick(f0_: vec3, f90_: f32, VoH: f32) -> vec3 { @@ -237,13 +249,14 @@ fn fresnel(f0_3: vec3, LoH: f32) -> vec3 { f0_4 = f0_3; LoH1 = LoH; - let _e44: vec3 = f0_4; - f90_4 = clamp(dot(_e44, vec3((50.0 * 0.33000001311302185))), 0.0, 1.0); - let _e57: vec3 = f0_4; - let _e58: f32 = f90_4; - let _e59: f32 = LoH1; - let _e60: vec3 = F_Schlick(_e57, _e58, _e59); - return _e60; + let _e49: vec3 = f0_4; + let _e62: vec3 = f0_4; + f90_4 = clamp(dot(_e62, vec3((50.0 * 0.33000001311302185))), 0.0, 1.0); + let _e75: vec3 = f0_4; + let _e76: f32 = f90_4; + let _e77: f32 = LoH1; + let _e78: vec3 = F_Schlick(_e75, _e76, _e77); + return _e78; } fn specular(f0_5: vec3, roughness4: f32, h1: vec3, NoV2: f32, NoL2: f32, NoH2: f32, LoH2: f32, specularIntensity: f32) -> vec3 { @@ -335,16 +348,21 @@ fn EnvBRDFApprox(f0_7: vec3, perceptual_roughness: f32, NoV6: f32) -> vec3< let _e69: vec4 = r; let _e71: vec4 = r; let _e76: f32 = NoV7; - let _e80: vec4 = r; + let _e80: f32 = NoV7; let _e83: vec4 = r; - a004_ = ((min((_e69.x * _e71.x), exp2((-(9.279999732971191) * _e76))) * _e80.x) + _e83.y); - let _e91: f32 = a004_; - let _e94: vec4 = r; - AB = ((vec2(-(1.0399999618530273), 1.0399999618530273) * vec2(_e91)) + _e94.zw); - let _e98: vec3 = f0_8; - let _e99: vec2 = AB; - let _e103: vec2 = AB; - return ((_e98 * vec3(_e99.x)) + vec3(_e103.y)); + let _e85: vec4 = r; + let _e90: f32 = NoV7; + let _e94: f32 = NoV7; + let _e98: vec4 = r; + let _e101: vec4 = r; + a004_ = ((min((_e83.x * _e85.x), exp2((-(9.279999732971191) * _e94))) * _e98.x) + _e101.y); + let _e109: f32 = a004_; + let _e112: vec4 = r; + AB = ((vec2(-(1.0399999618530273), 1.0399999618530273) * vec2(_e109)) + _e112.zw); + let _e116: vec3 = f0_8; + let _e117: vec2 = AB; + let _e121: vec2 = AB; + return ((_e116 * vec3(_e117.x)) + vec3(_e121.y)); } fn perceptualRoughnessToRoughness(perceptualRoughness: f32) -> f32 { @@ -352,11 +370,11 @@ fn perceptualRoughnessToRoughness(perceptualRoughness: f32) -> f32 { var clampedPerceptualRoughness: f32; perceptualRoughness1 = perceptualRoughness; - let _e42: f32 = perceptualRoughness1; - clampedPerceptualRoughness = clamp(_e42, 0.08900000154972076, 1.0); - let _e47: f32 = clampedPerceptualRoughness; - let _e48: f32 = clampedPerceptualRoughness; - return (_e47 * _e48); + let _e45: f32 = perceptualRoughness1; + clampedPerceptualRoughness = clamp(_e45, 0.08900000154972076, 1.0); + let _e50: f32 = clampedPerceptualRoughness; + let _e51: f32 = clampedPerceptualRoughness; + return (_e50 * _e51); } fn reinhard(color: vec3) -> vec3 { @@ -389,8 +407,8 @@ fn luminance(v1: vec3) -> f32 { var v2: vec3; v2 = v1; - let _e42: vec3 = v2; - return dot(_e42, vec3(0.2125999927520752, 0.7152000069618225, 0.0722000002861023)); + let _e47: vec3 = v2; + return dot(_e47, vec3(0.2125999927520752, 0.7152000069618225, 0.0722000002861023)); } fn change_luminance(c_in: vec3, l_out: f32) -> vec3 { @@ -491,92 +509,120 @@ fn point_light(light: PointLight, roughness8: f32, NdotV: f32, N: vec3, V1: let _e56: PointLight = light1; let _e59: vec3 = v_WorldPosition1; light_to_frag = (_e56.pos.xyz - _e59.xyz); - let _e63: vec3 = light_to_frag; - let _e64: vec3 = light_to_frag; - distance_square = dot(_e63, _e64); - let _e68: PointLight = light1; - let _e71: f32 = distance_square; - let _e72: PointLight = light1; - let _e75: f32 = getDistanceAttenuation(_e71, _e72.lightParams.x); - rangeAttenuation = _e75; - let _e77: f32 = roughness9; - a1 = _e77; - let _e79: PointLight = light1; - radius = _e79.lightParams.y; - let _e83: vec3 = light_to_frag; - let _e84: vec3 = R1; - let _e86: vec3 = R1; - let _e88: vec3 = light_to_frag; - centerToRay = ((dot(_e83, _e84) * _e86) - _e88); - let _e91: vec3 = light_to_frag; - let _e92: vec3 = centerToRay; - let _e93: f32 = radius; - let _e94: vec3 = centerToRay; - let _e95: vec3 = centerToRay; - closestPoint = (_e91 + (_e92 * clamp((_e93 * inverseSqrt(dot(_e94, _e95))), 0.0, 1.0))); - let _e105: vec3 = closestPoint; - let _e106: vec3 = closestPoint; - LspecLengthInverse = inverseSqrt(dot(_e105, _e106)); - let _e110: f32 = a1; - let _e111: f32 = a1; + let _e65: vec3 = light_to_frag; + let _e66: vec3 = light_to_frag; + distance_square = dot(_e65, _e66); + let _e70: PointLight = light1; + let _e73: f32 = distance_square; + let _e74: PointLight = light1; + let _e77: f32 = getDistanceAttenuation(_e73, _e74.lightParams.x); + rangeAttenuation = _e77; + let _e79: f32 = roughness9; + a1 = _e79; + let _e81: PointLight = light1; + radius = _e81.lightParams.y; + let _e87: vec3 = light_to_frag; + let _e88: vec3 = R1; + let _e90: vec3 = R1; + let _e92: vec3 = light_to_frag; + centerToRay = ((dot(_e87, _e88) * _e90) - _e92); + let _e95: vec3 = light_to_frag; + let _e96: vec3 = centerToRay; + let _e97: f32 = radius; + let _e100: vec3 = centerToRay; + let _e101: vec3 = centerToRay; + let _e105: vec3 = centerToRay; + let _e106: vec3 = centerToRay; let _e112: f32 = radius; - let _e115: f32 = LspecLengthInverse; - normalizationFactor = (_e110 / clamp((_e111 + ((_e112 * 0.5) * _e115)), 0.0, 1.0)); - let _e123: f32 = normalizationFactor; - let _e124: f32 = normalizationFactor; - specularIntensity2 = (_e123 * _e124); - let _e127: vec3 = closestPoint; - let _e128: f32 = LspecLengthInverse; - L = (_e127 * _e128); - let _e131: vec3 = L; - let _e132: vec3 = V2; - H = normalize((_e131 + _e132)); - let _e136: vec3 = N1; - let _e137: vec3 = L; - NoL6 = clamp(dot(_e136, _e137), 0.0, 1.0); - let _e143: vec3 = N1; - let _e144: vec3 = H; - NoH4 = clamp(dot(_e143, _e144), 0.0, 1.0); - let _e150: vec3 = L; - let _e151: vec3 = H; - LoH6 = clamp(dot(_e150, _e151), 0.0, 1.0); - let _e165: vec3 = F0_1; - let _e166: f32 = roughness9; - let _e167: vec3 = H; - let _e168: f32 = NdotV1; - let _e169: f32 = NoL6; - let _e170: f32 = NoH4; - let _e171: f32 = LoH6; - let _e172: f32 = specularIntensity2; - let _e173: vec3 = specular(_e165, _e166, _e167, _e168, _e169, _e170, _e171, _e172); - specular1 = _e173; - let _e175: vec3 = light_to_frag; - L = normalize(_e175); - let _e177: vec3 = L; - let _e178: vec3 = V2; - H = normalize((_e177 + _e178)); - let _e181: vec3 = N1; - let _e182: vec3 = L; - NoL6 = clamp(dot(_e181, _e182), 0.0, 1.0); - let _e187: vec3 = N1; - let _e188: vec3 = H; - NoH4 = clamp(dot(_e187, _e188), 0.0, 1.0); - let _e193: vec3 = L; - let _e194: vec3 = H; - LoH6 = clamp(dot(_e193, _e194), 0.0, 1.0); - let _e199: vec3 = diffuseColor1; - let _e204: f32 = roughness9; - let _e205: f32 = NdotV1; - let _e206: f32 = NoL6; - let _e207: f32 = LoH6; - let _e208: f32 = Fd_Burley(_e204, _e205, _e206, _e207); - diffuse = (_e199 * _e208); - let _e211: vec3 = diffuse; - let _e212: vec3 = specular1; - let _e214: PointLight = light1; - let _e218: f32 = rangeAttenuation; - let _e219: f32 = NoL6; - return (((_e211 + _e212) * _e214.color.xyz) * (_e218 * _e219)); + let _e115: vec3 = centerToRay; + let _e116: vec3 = centerToRay; + let _e120: vec3 = centerToRay; + let _e121: vec3 = centerToRay; + closestPoint = (_e95 + (_e96 * clamp((_e112 * inverseSqrt(dot(_e120, _e121))), 0.0, 1.0))); + let _e133: vec3 = closestPoint; + let _e134: vec3 = closestPoint; + let _e138: vec3 = closestPoint; + let _e139: vec3 = closestPoint; + LspecLengthInverse = inverseSqrt(dot(_e138, _e139)); + let _e143: f32 = a1; + let _e144: f32 = a1; + let _e145: f32 = radius; + let _e148: f32 = LspecLengthInverse; + let _e153: f32 = a1; + let _e154: f32 = radius; + let _e157: f32 = LspecLengthInverse; + normalizationFactor = (_e143 / clamp((_e153 + ((_e154 * 0.5) * _e157)), 0.0, 1.0)); + let _e165: f32 = normalizationFactor; + let _e166: f32 = normalizationFactor; + specularIntensity2 = (_e165 * _e166); + let _e169: vec3 = closestPoint; + let _e170: f32 = LspecLengthInverse; + L = (_e169 * _e170); + let _e173: vec3 = L; + let _e174: vec3 = V2; + let _e176: vec3 = L; + let _e177: vec3 = V2; + H = normalize((_e176 + _e177)); + let _e183: vec3 = N1; + let _e184: vec3 = L; + let _e190: vec3 = N1; + let _e191: vec3 = L; + NoL6 = clamp(dot(_e190, _e191), 0.0, 1.0); + let _e199: vec3 = N1; + let _e200: vec3 = H; + let _e206: vec3 = N1; + let _e207: vec3 = H; + NoH4 = clamp(dot(_e206, _e207), 0.0, 1.0); + let _e215: vec3 = L; + let _e216: vec3 = H; + let _e222: vec3 = L; + let _e223: vec3 = H; + LoH6 = clamp(dot(_e222, _e223), 0.0, 1.0); + let _e237: vec3 = F0_1; + let _e238: f32 = roughness9; + let _e239: vec3 = H; + let _e240: f32 = NdotV1; + let _e241: f32 = NoL6; + let _e242: f32 = NoH4; + let _e243: f32 = LoH6; + let _e244: f32 = specularIntensity2; + let _e245: vec3 = specular(_e237, _e238, _e239, _e240, _e241, _e242, _e243, _e244); + specular1 = _e245; + let _e248: vec3 = light_to_frag; + L = normalize(_e248); + let _e250: vec3 = L; + let _e251: vec3 = V2; + let _e253: vec3 = L; + let _e254: vec3 = V2; + H = normalize((_e253 + _e254)); + let _e259: vec3 = N1; + let _e260: vec3 = L; + let _e266: vec3 = N1; + let _e267: vec3 = L; + NoL6 = clamp(dot(_e266, _e267), 0.0, 1.0); + let _e274: vec3 = N1; + let _e275: vec3 = H; + let _e281: vec3 = N1; + let _e282: vec3 = H; + NoH4 = clamp(dot(_e281, _e282), 0.0, 1.0); + let _e289: vec3 = L; + let _e290: vec3 = H; + let _e296: vec3 = L; + let _e297: vec3 = H; + LoH6 = clamp(dot(_e296, _e297), 0.0, 1.0); + let _e302: vec3 = diffuseColor1; + let _e307: f32 = roughness9; + let _e308: f32 = NdotV1; + let _e309: f32 = NoL6; + let _e310: f32 = LoH6; + let _e311: f32 = Fd_Burley(_e307, _e308, _e309, _e310); + diffuse = (_e302 * _e311); + let _e314: vec3 = diffuse; + let _e315: vec3 = specular1; + let _e317: PointLight = light1; + let _e321: f32 = rangeAttenuation; + let _e322: f32 = NoL6; + return (((_e314 + _e315) * _e317.color.xyz) * (_e321 * _e322)); } fn dir_light(light2: DirectionalLight, roughness10: f32, NdotV2: f32, normal: vec3, view: vec3, R2: vec3, F0_2: vec3, diffuseColor2: vec3) -> vec3 { @@ -609,38 +655,46 @@ fn dir_light(light2: DirectionalLight, roughness10: f32, NdotV2: f32, normal: ve incident_light = _e56.direction.xyz; let _e60: vec3 = incident_light; let _e61: vec3 = view1; - half_vector = normalize((_e60 + _e61)); - let _e65: vec3 = normal1; - let _e66: vec3 = incident_light; - NoL7 = clamp(dot(_e65, _e66), 0.0, 1.0); - let _e72: vec3 = normal1; - let _e73: vec3 = half_vector; - NoH5 = clamp(dot(_e72, _e73), 0.0, 1.0); - let _e79: vec3 = incident_light; - let _e80: vec3 = half_vector; - LoH7 = clamp(dot(_e79, _e80), 0.0, 1.0); - let _e86: vec3 = diffuseColor3; - let _e91: f32 = roughness11; - let _e92: f32 = NdotV3; - let _e93: f32 = NoL7; - let _e94: f32 = LoH7; - let _e95: f32 = Fd_Burley(_e91, _e92, _e93, _e94); - diffuse1 = (_e86 * _e95); - let _e108: vec3 = F0_3; - let _e109: f32 = roughness11; + let _e63: vec3 = incident_light; + let _e64: vec3 = view1; + half_vector = normalize((_e63 + _e64)); + let _e70: vec3 = normal1; + let _e71: vec3 = incident_light; + let _e77: vec3 = normal1; + let _e78: vec3 = incident_light; + NoL7 = clamp(dot(_e77, _e78), 0.0, 1.0); + let _e86: vec3 = normal1; + let _e87: vec3 = half_vector; + let _e93: vec3 = normal1; + let _e94: vec3 = half_vector; + NoH5 = clamp(dot(_e93, _e94), 0.0, 1.0); + let _e102: vec3 = incident_light; + let _e103: vec3 = half_vector; + let _e109: vec3 = incident_light; let _e110: vec3 = half_vector; - let _e111: f32 = NdotV3; - let _e112: f32 = NoL7; - let _e113: f32 = NoH5; - let _e114: f32 = LoH7; - let _e115: f32 = specularIntensity3; - let _e116: vec3 = specular(_e108, _e109, _e110, _e111, _e112, _e113, _e114, _e115); - specular2 = _e116; - let _e118: vec3 = specular2; - let _e119: vec3 = diffuse1; - let _e121: DirectionalLight = light3; - let _e125: f32 = NoL7; - return (((_e118 + _e119) * _e121.color.xyz) * _e125); + LoH7 = clamp(dot(_e109, _e110), 0.0, 1.0); + let _e116: vec3 = diffuseColor3; + let _e121: f32 = roughness11; + let _e122: f32 = NdotV3; + let _e123: f32 = NoL7; + let _e124: f32 = LoH7; + let _e125: f32 = Fd_Burley(_e121, _e122, _e123, _e124); + diffuse1 = (_e116 * _e125); + let _e138: vec3 = F0_3; + let _e139: f32 = roughness11; + let _e140: vec3 = half_vector; + let _e141: f32 = NdotV3; + let _e142: f32 = NoL7; + let _e143: f32 = NoH5; + let _e144: f32 = LoH7; + let _e145: f32 = specularIntensity3; + let _e146: vec3 = specular(_e138, _e139, _e140, _e141, _e142, _e143, _e144, _e145); + specular2 = _e146; + let _e148: vec3 = specular2; + let _e149: vec3 = diffuse1; + let _e151: DirectionalLight = light3; + let _e155: f32 = NoL7; + return (((_e148 + _e149) * _e151.color.xyz) * _e155); } fn main1() { @@ -669,175 +723,183 @@ fn main1() { let _e40: vec4 = global3.base_color; output_color = _e40; let _e42: vec4 = output_color; - let _e43: vec2 = v_Uv1; - let _e44: vec4 = textureSample(StandardMaterial_base_color_texture, StandardMaterial_base_color_texture_sampler, _e43); - output_color = (_e42 * _e44); - let _e46: vec2 = v_Uv1; - let _e47: vec4 = textureSample(StandardMaterial_metallic_roughness_texture, StandardMaterial_metallic_roughness_texture_sampler, _e46); - metallic_roughness = _e47; - let _e49: f32 = global5.metallic; - let _e50: vec4 = metallic_roughness; - metallic = (_e49 * _e50.z); - let _e54: f32 = global4.perceptual_roughness; - let _e55: vec4 = metallic_roughness; - perceptual_roughness2 = (_e54 * _e55.y); - let _e60: f32 = perceptual_roughness2; - let _e61: f32 = perceptualRoughnessToRoughness(_e60); - roughness12 = _e61; - let _e63: vec3 = v_WorldNormal1; - N2 = normalize(_e63); - let _e66: vec4 = v_WorldTangent1; - T = normalize(_e66.xyz); - let _e70: vec3 = N2; - let _e71: vec3 = T; - let _e73: vec4 = v_WorldTangent1; - B = (cross(_e70, _e71) * _e73.w); - let _e78: bool = gl_FrontFacing; - let _e79: vec3 = N2; - let _e80: vec3 = N2; - N2 = select(-(_e80), _e79, _e78); - let _e83: bool = gl_FrontFacing; - let _e84: vec3 = T; - let _e85: vec3 = T; - T = select(-(_e85), _e84, _e83); - let _e88: bool = gl_FrontFacing; - let _e89: vec3 = B; - let _e90: vec3 = B; - B = select(-(_e90), _e89, _e88); - let _e93: vec3 = T; - let _e94: vec3 = B; - let _e95: vec3 = N2; - TBN = mat3x3(vec3(_e93.x, _e93.y, _e93.z), vec3(_e94.x, _e94.y, _e94.z), vec3(_e95.x, _e95.y, _e95.z)); - let _e110: mat3x3 = TBN; - let _e111: vec2 = v_Uv1; - let _e112: vec4 = textureSample(StandardMaterial_normal_map, StandardMaterial_normal_map_sampler, _e111); - N2 = (_e110 * normalize(((_e112.xyz * 2.0) - vec3(1.0)))); - let _e121: vec2 = v_Uv1; - let _e122: vec4 = textureSample(StandardMaterial_occlusion_texture, StandardMaterial_occlusion_texture_sampler, _e121); - occlusion = _e122.x; - let _e125: vec4 = global7.emissive; - emissive = _e125; - let _e127: vec4 = emissive; - let _e129: vec4 = emissive; - let _e131: vec2 = v_Uv1; - let _e132: vec4 = textureSample(StandardMaterial_emissive_texture, StandardMaterial_emissive_texture_sampler, _e131); - let _e134: vec3 = (_e129.xyz * _e132.xyz); - emissive.x = _e134.x; - emissive.y = _e134.y; - emissive.z = _e134.z; - let _e141: vec4 = global1.CameraPos; - let _e143: vec3 = v_WorldPosition1; - V3 = normalize((_e141.xyz - _e143.xyz)); - let _e148: vec3 = N2; - let _e149: vec3 = V3; - NdotV4 = max(dot(_e148, _e149), 0.00009999999747378752); - let _e155: f32 = global6.reflectance; - let _e157: f32 = global6.reflectance; - let _e160: f32 = metallic; - let _e164: vec4 = output_color; - let _e166: f32 = metallic; - F0_4 = (vec3((((0.1599999964237213 * _e155) * _e157) * (1.0 - _e160))) + (_e164.xyz * vec3(_e166))); - let _e171: vec4 = output_color; - let _e174: f32 = metallic; - diffuseColor4 = (_e171.xyz * vec3((1.0 - _e174))); - let _e179: vec3 = V3; - let _e181: vec3 = N2; - R4 = reflect(-(_e179), _e181); + let _e44: vec2 = v_Uv1; + let _e45: vec4 = textureSample(StandardMaterial_base_color_texture, StandardMaterial_base_color_texture_sampler, _e44); + output_color = (_e42 * _e45); + let _e48: vec2 = v_Uv1; + let _e49: vec4 = textureSample(StandardMaterial_metallic_roughness_texture, StandardMaterial_metallic_roughness_texture_sampler, _e48); + metallic_roughness = _e49; + let _e51: f32 = global5.metallic; + let _e52: vec4 = metallic_roughness; + metallic = (_e51 * _e52.z); + let _e56: f32 = global4.perceptual_roughness; + let _e57: vec4 = metallic_roughness; + perceptual_roughness2 = (_e56 * _e57.y); + let _e62: f32 = perceptual_roughness2; + let _e63: f32 = perceptualRoughnessToRoughness(_e62); + roughness12 = _e63; + let _e66: vec3 = v_WorldNormal1; + N2 = normalize(_e66); + let _e69: vec4 = v_WorldTangent1; + let _e71: vec4 = v_WorldTangent1; + T = normalize(_e71.xyz); + let _e77: vec3 = N2; + let _e78: vec3 = T; + let _e80: vec4 = v_WorldTangent1; + B = (cross(_e77, _e78) * _e80.w); + let _e85: bool = gl_FrontFacing; + let _e86: vec3 = N2; + let _e87: vec3 = N2; + N2 = select(-(_e87), _e86, _e85); + let _e90: bool = gl_FrontFacing; + let _e91: vec3 = T; + let _e92: vec3 = T; + T = select(-(_e92), _e91, _e90); + let _e95: bool = gl_FrontFacing; + let _e96: vec3 = B; + let _e97: vec3 = B; + B = select(-(_e97), _e96, _e95); + let _e100: vec3 = T; + let _e101: vec3 = B; + let _e102: vec3 = N2; + TBN = mat3x3(vec3(_e100.x, _e100.y, _e100.z), vec3(_e101.x, _e101.y, _e101.z), vec3(_e102.x, _e102.y, _e102.z)); + let _e117: mat3x3 = TBN; + let _e119: vec2 = v_Uv1; + let _e120: vec4 = textureSample(StandardMaterial_normal_map, StandardMaterial_normal_map_sampler, _e119); + let _e128: vec2 = v_Uv1; + let _e129: vec4 = textureSample(StandardMaterial_normal_map, StandardMaterial_normal_map_sampler, _e128); + N2 = (_e117 * normalize(((_e129.xyz * 2.0) - vec3(1.0)))); + let _e139: vec2 = v_Uv1; + let _e140: vec4 = textureSample(StandardMaterial_occlusion_texture, StandardMaterial_occlusion_texture_sampler, _e139); + occlusion = _e140.x; + let _e143: vec4 = global7.emissive; + emissive = _e143; + let _e145: vec4 = emissive; + let _e147: vec4 = emissive; + let _e150: vec2 = v_Uv1; + let _e151: vec4 = textureSample(StandardMaterial_emissive_texture, StandardMaterial_emissive_texture_sampler, _e150); + let _e153: vec3 = (_e147.xyz * _e151.xyz); + emissive.x = _e153.x; + emissive.y = _e153.y; + emissive.z = _e153.z; + let _e160: vec4 = global1.CameraPos; + let _e162: vec3 = v_WorldPosition1; + let _e165: vec4 = global1.CameraPos; + let _e167: vec3 = v_WorldPosition1; + V3 = normalize((_e165.xyz - _e167.xyz)); + let _e174: vec3 = N2; + let _e175: vec3 = V3; + let _e180: vec3 = N2; + let _e181: vec3 = V3; + NdotV4 = max(dot(_e180, _e181), 0.00009999999747378752); + let _e187: f32 = global6.reflectance; + let _e189: f32 = global6.reflectance; + let _e192: f32 = metallic; + let _e196: vec4 = output_color; + let _e198: f32 = metallic; + F0_4 = (vec3((((0.1599999964237213 * _e187) * _e189) * (1.0 - _e192))) + (_e196.xyz * vec3(_e198))); + let _e203: vec4 = output_color; + let _e206: f32 = metallic; + diffuseColor4 = (_e203.xyz * vec3((1.0 - _e206))); + let _e211: vec3 = V3; + let _e214: vec3 = V3; + let _e216: vec3 = N2; + R4 = reflect(-(_e214), _e216); loop { - let _e189: i32 = i; - let _e190: vec4 = global2.NumLights; - let _e194: i32 = i; - if (!(((_e189 < i32(_e190.x)) && (_e194 < 10)))) { + let _e224: i32 = i; + let _e225: vec4 = global2.NumLights; + let _e229: i32 = i; + if (!(((_e224 < i32(_e225.x)) && (_e229 < 10)))) { break; } { - let _e201: vec3 = light_accum; - let _e202: i32 = i; - let _e212: i32 = i; - let _e214: PointLight = global2.PointLights[_e212]; - let _e215: f32 = roughness12; - let _e216: f32 = NdotV4; - let _e217: vec3 = N2; - let _e218: vec3 = V3; - let _e219: vec3 = R4; - let _e220: vec3 = F0_4; - let _e221: vec3 = diffuseColor4; - let _e222: vec3 = point_light(_e214, _e215, _e216, _e217, _e218, _e219, _e220, _e221); - light_accum = (_e201 + _e222); + let _e236: vec3 = light_accum; + let _e237: i32 = i; + let _e247: i32 = i; + let _e249: PointLight = global2.PointLights[_e247]; + let _e250: f32 = roughness12; + let _e251: f32 = NdotV4; + let _e252: vec3 = N2; + let _e253: vec3 = V3; + let _e254: vec3 = R4; + let _e255: vec3 = F0_4; + let _e256: vec3 = diffuseColor4; + let _e257: vec3 = point_light(_e249, _e250, _e251, _e252, _e253, _e254, _e255, _e256); + light_accum = (_e236 + _e257); } continuing { - let _e198: i32 = i; - i = (_e198 + 1); + let _e233: i32 = i; + i = (_e233 + 1); } } loop { - let _e226: i32 = i1; - let _e227: vec4 = global2.NumLights; - let _e231: i32 = i1; - if (!(((_e226 < i32(_e227.y)) && (_e231 < 1)))) { + let _e261: i32 = i1; + let _e262: vec4 = global2.NumLights; + let _e266: i32 = i1; + if (!(((_e261 < i32(_e262.y)) && (_e266 < 1)))) { break; } { - let _e238: vec3 = light_accum; - let _e239: i32 = i1; - let _e249: i32 = i1; - let _e251: DirectionalLight = global2.DirectionalLights[_e249]; - let _e252: f32 = roughness12; - let _e253: f32 = NdotV4; - let _e254: vec3 = N2; - let _e255: vec3 = V3; - let _e256: vec3 = R4; - let _e257: vec3 = F0_4; - let _e258: vec3 = diffuseColor4; - let _e259: vec3 = dir_light(_e251, _e252, _e253, _e254, _e255, _e256, _e257, _e258); - light_accum = (_e238 + _e259); + let _e273: vec3 = light_accum; + let _e274: i32 = i1; + let _e284: i32 = i1; + let _e286: DirectionalLight = global2.DirectionalLights[_e284]; + let _e287: f32 = roughness12; + let _e288: f32 = NdotV4; + let _e289: vec3 = N2; + let _e290: vec3 = V3; + let _e291: vec3 = R4; + let _e292: vec3 = F0_4; + let _e293: vec3 = diffuseColor4; + let _e294: vec3 = dir_light(_e286, _e287, _e288, _e289, _e290, _e291, _e292, _e293); + light_accum = (_e273 + _e294); } continuing { - let _e235: i32 = i1; - i1 = (_e235 + 1); + let _e270: i32 = i1; + i1 = (_e270 + 1); } } - let _e264: vec3 = diffuseColor4; - let _e266: f32 = NdotV4; - let _e267: vec3 = EnvBRDFApprox(_e264, 1.0, _e266); - diffuse_ambient = _e267; - let _e272: vec3 = F0_4; - let _e273: f32 = perceptual_roughness2; - let _e274: f32 = NdotV4; - let _e275: vec3 = EnvBRDFApprox(_e272, _e273, _e274); - specular_ambient = _e275; - let _e277: vec4 = output_color; - let _e279: vec3 = light_accum; - output_color.x = _e279.x; - output_color.y = _e279.y; - output_color.z = _e279.z; - let _e286: vec4 = output_color; - let _e288: vec4 = output_color; - let _e290: vec3 = diffuse_ambient; - let _e291: vec3 = specular_ambient; - let _e293: vec4 = global2.AmbientColor; - let _e296: f32 = occlusion; - let _e298: vec3 = (_e288.xyz + (((_e290 + _e291) * _e293.xyz) * _e296)); - output_color.x = _e298.x; - output_color.y = _e298.y; - output_color.z = _e298.z; - let _e305: vec4 = output_color; - let _e307: vec4 = output_color; - let _e309: vec4 = emissive; - let _e311: vec4 = output_color; - let _e314: vec3 = (_e307.xyz + (_e309.xyz * _e311.w)); + let _e299: vec3 = diffuseColor4; + let _e301: f32 = NdotV4; + let _e302: vec3 = EnvBRDFApprox(_e299, 1.0, _e301); + diffuse_ambient = _e302; + let _e307: vec3 = F0_4; + let _e308: f32 = perceptual_roughness2; + let _e309: f32 = NdotV4; + let _e310: vec3 = EnvBRDFApprox(_e307, _e308, _e309); + specular_ambient = _e310; + let _e312: vec4 = output_color; + let _e314: vec3 = light_accum; output_color.x = _e314.x; output_color.y = _e314.y; output_color.z = _e314.z; let _e321: vec4 = output_color; let _e323: vec4 = output_color; - let _e325: vec4 = output_color; - let _e327: vec3 = reinhard_luminance(_e325.xyz); - output_color.x = _e327.x; - output_color.y = _e327.y; - output_color.z = _e327.z; - let _e334: vec4 = output_color; - o_Target = _e334; + let _e325: vec3 = diffuse_ambient; + let _e326: vec3 = specular_ambient; + let _e328: vec4 = global2.AmbientColor; + let _e331: f32 = occlusion; + let _e333: vec3 = (_e323.xyz + (((_e325 + _e326) * _e328.xyz) * _e331)); + output_color.x = _e333.x; + output_color.y = _e333.y; + output_color.z = _e333.z; + let _e340: vec4 = output_color; + let _e342: vec4 = output_color; + let _e344: vec4 = emissive; + let _e346: vec4 = output_color; + let _e349: vec3 = (_e342.xyz + (_e344.xyz * _e346.w)); + output_color.x = _e349.x; + output_color.y = _e349.y; + output_color.z = _e349.z; + let _e356: vec4 = output_color; + let _e358: vec4 = output_color; + let _e360: vec4 = output_color; + let _e362: vec3 = reinhard_luminance(_e360.xyz); + output_color.x = _e362.x; + output_color.y = _e362.y; + output_color.z = _e362.z; + let _e369: vec4 = output_color; + o_Target = _e369; return; } diff --git a/tests/out/wgsl/bool-select-frag.wgsl b/tests/out/wgsl/bool-select-frag.wgsl index bf0e64fb4b..9f26d9d76a 100644 --- a/tests/out/wgsl/bool-select-frag.wgsl +++ b/tests/out/wgsl/bool-select-frag.wgsl @@ -21,9 +21,9 @@ fn TevPerCompGT1(a2: vec3, b2: vec3) -> vec3 { a3 = a2; b3 = b2; - let _e5: vec3 = a3; - let _e6: vec3 = b3; - return select(vec3(0.0), vec3(1.0), (_e5 > _e6)); + let _e7: vec3 = a3; + let _e8: vec3 = b3; + return select(vec3(0.0), vec3(1.0), (_e7 > _e8)); } fn main1() { diff --git a/tests/out/wgsl/clamp-splat-vert.wgsl b/tests/out/wgsl/clamp-splat-vert.wgsl index 3c9ec4535b..bbc28b22a4 100644 --- a/tests/out/wgsl/clamp-splat-vert.wgsl +++ b/tests/out/wgsl/clamp-splat-vert.wgsl @@ -6,8 +6,8 @@ var a_pos1: vec2; var gl_Position: vec4; fn main1() { - let _e2: vec2 = a_pos1; - gl_Position = vec4(clamp(_e2, vec2(0.0), vec2(1.0)), 0.0, 1.0); + let _e5: vec2 = a_pos1; + gl_Position = vec4(clamp(_e5, vec2(0.0), vec2(1.0)), 0.0, 1.0); return; } diff --git a/tests/out/wgsl/math-functions-vert.wgsl b/tests/out/wgsl/math-functions-vert.wgsl index 03ec93e054..32602b9b5a 100644 --- a/tests/out/wgsl/math-functions-vert.wgsl +++ b/tests/out/wgsl/math-functions-vert.wgsl @@ -48,95 +48,102 @@ fn main1() { let _e8: vec4 = a; let _e9: vec4 = b; m = mat4x4(vec4(_e6.x, _e6.y, _e6.z, _e6.w), vec4(_e7.x, _e7.y, _e7.z, _e7.w), vec4(_e8.x, _e8.y, _e8.z, _e8.w), vec4(_e9.x, _e9.y, _e9.z, _e9.w)); - let _e34: vec4 = a; - ceilOut = ceil(_e34); - let _e37: vec4 = a; - roundOut = round(_e37); - let _e40: vec4 = a; - floorOut = floor(_e40); + let _e35: vec4 = a; + ceilOut = ceil(_e35); + let _e39: vec4 = a; + roundOut = round(_e39); let _e43: vec4 = a; - fractOut = fract(_e43); - let _e46: vec4 = a; - truncOut = trunc(_e46); - let _e49: vec4 = a; - sinOut = sin(_e49); - let _e52: vec4 = a; - absOut = abs(_e52); + floorOut = floor(_e43); + let _e47: vec4 = a; + fractOut = fract(_e47); + let _e51: vec4 = a; + truncOut = trunc(_e51); let _e55: vec4 = a; - sqrtOut = sqrt(_e55); - let _e58: vec4 = a; - inversesqrtOut = inverseSqrt(_e58); - let _e61: vec4 = a; - expOut = exp(_e61); - let _e64: vec4 = a; - exp2Out = exp2(_e64); + sinOut = sin(_e55); + let _e59: vec4 = a; + absOut = abs(_e59); + let _e63: vec4 = a; + sqrtOut = sqrt(_e63); let _e67: vec4 = a; - signOut = sign(_e67); - let _e70: mat4x4 = m; - transposeOut = transpose(_e70); - let _e73: vec4 = a; - normalizeOut = normalize(_e73); - let _e76: vec4 = a; - sinhOut = sinh(_e76); + inversesqrtOut = inverseSqrt(_e67); + let _e71: vec4 = a; + expOut = exp(_e71); + let _e75: vec4 = a; + exp2Out = exp2(_e75); let _e79: vec4 = a; - cosOut = cos(_e79); - let _e82: vec4 = a; - coshOut = cosh(_e82); - let _e85: vec4 = a; - tanOut = tan(_e85); - let _e88: vec4 = a; - tanhOut = tanh(_e88); + signOut = sign(_e79); + let _e83: mat4x4 = m; + transposeOut = transpose(_e83); + let _e87: vec4 = a; + normalizeOut = normalize(_e87); let _e91: vec4 = a; - acosOut = acos(_e91); - let _e94: vec4 = a; - asinOut = asin(_e94); - let _e97: vec4 = a; - logOut = log(_e97); - let _e100: vec4 = a; - log2Out = log2(_e100); + sinhOut = sinh(_e91); + let _e95: vec4 = a; + cosOut = cos(_e95); + let _e99: vec4 = a; + coshOut = cosh(_e99); let _e103: vec4 = a; - lengthOut = length(_e103); - let _e106: mat4x4 = m; - determinantOut = determinant(_e106); - let _e109: i32 = i; - bitCountOut = countOneBits(_e109); - let _e112: i32 = i; - bitfieldReverseOut = reverseBits(_e112); + tanOut = tan(_e103); + let _e107: vec4 = a; + tanhOut = tanh(_e107); + let _e111: vec4 = a; + acosOut = acos(_e111); let _e115: vec4 = a; - atanOut = atan(_e115.x); + asinOut = asin(_e115); let _e119: vec4 = a; - let _e121: vec4 = a; - atan2Out = atan2(_e119.x, _e121.y); - let _e125: vec4 = a; - let _e127: vec4 = b; - modOut = (_e125.x % _e127.x); - let _e131: vec4 = a; - let _e132: vec4 = b; - powOut = pow(_e131, _e132); - let _e135: vec4 = a; - let _e136: vec4 = b; - dotOut = dot(_e135, _e136); - let _e139: vec4 = a; - let _e140: vec4 = b; - maxOut = max(_e139, _e140); - let _e143: vec4 = a; - let _e144: vec4 = b; - minOut = min(_e143, _e144); - let _e147: vec4 = a; - let _e148: vec4 = b; - reflectOut = reflect(_e147, _e148); - let _e151: vec4 = a; - let _e153: vec4 = b; - crossOut = cross(_e151.xyz, _e153.xyz); - let _e157: vec4 = a; - let _e158: vec4 = b; - outerProductOut = outerProduct(_e157, _e158); - let _e161: vec4 = a; - let _e162: vec4 = b; - distanceOut = distance(_e161, _e162); - let _e165: vec4 = a; - let _e166: vec4 = b; - stepOut = step(_e165, _e166); + logOut = log(_e119); + let _e123: vec4 = a; + log2Out = log2(_e123); + let _e127: vec4 = a; + lengthOut = length(_e127); + let _e131: mat4x4 = m; + determinantOut = determinant(_e131); + let _e135: i32 = i; + bitCountOut = countOneBits(_e135); + let _e139: i32 = i; + bitfieldReverseOut = reverseBits(_e139); + let _e142: vec4 = a; + let _e144: vec4 = a; + atanOut = atan(_e144.x); + let _e148: vec4 = a; + let _e150: vec4 = a; + let _e152: vec4 = a; + let _e154: vec4 = a; + atan2Out = atan2(_e152.x, _e154.y); + let _e158: vec4 = a; + let _e160: vec4 = b; + let _e162: vec4 = a; + let _e164: vec4 = b; + modOut = (_e162.x % _e164.x); + let _e170: vec4 = a; + let _e171: vec4 = b; + powOut = pow(_e170, _e171); + let _e176: vec4 = a; + let _e177: vec4 = b; + dotOut = dot(_e176, _e177); + let _e182: vec4 = a; + let _e183: vec4 = b; + maxOut = max(_e182, _e183); + let _e188: vec4 = a; + let _e189: vec4 = b; + minOut = min(_e188, _e189); + let _e194: vec4 = a; + let _e195: vec4 = b; + reflectOut = reflect(_e194, _e195); + let _e198: vec4 = a; + let _e200: vec4 = b; + let _e202: vec4 = a; + let _e204: vec4 = b; + crossOut = cross(_e202.xyz, _e204.xyz); + let _e210: vec4 = a; + let _e211: vec4 = b; + outerProductOut = outerProduct(_e210, _e211); + let _e216: vec4 = a; + let _e217: vec4 = b; + distanceOut = distance(_e216, _e217); + let _e222: vec4 = a; + let _e223: vec4 = b; + stepOut = step(_e222, _e223); return; }