Skip to content

Commit eb50ed5

Browse files
committed
Feature: Precalculate trig functions called with contant values.
E.g. f = cos(0.5) -> f = 0.87758
1 parent d74290b commit eb50ed5

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

ShaderShrinker/Shrinker.Parser/Optimizations/PerformArithmeticExtension.cs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
// -----------------------------------------------------------------------
1111

1212
using System;
13+
using System.Collections.Generic;
1314
using System.Linq;
1415
using Shrinker.Lexer;
1516
using Shrinker.Parser.SyntaxNodes;
@@ -123,8 +124,8 @@ public static bool PerformArithmetic(this SyntaxNode rootNode)
123124
}
124125

125126
// pow(1.1, 2.2) => <the result>
126-
foreach (var powNode in rootNode.TheTree
127-
.OfType<GlslFunctionCallSyntaxNode>()
127+
var functionCalls = rootNode.TheTree.OfType<GlslFunctionCallSyntaxNode>().ToList();
128+
foreach (var powNode in functionCalls
128129
.Where(o => o.Name == "pow" && o.Params.IsSimpleCsv())
129130
.ToList())
130131
{
@@ -137,32 +138,31 @@ public static bool PerformArithmetic(this SyntaxNode rootNode)
137138
}
138139
}
139140

140-
// abs(-1.1) => <the result>
141-
foreach (var absNode in rootNode.TheTree
142-
.OfType<GlslFunctionCallSyntaxNode>()
143-
.Where(o => o.Name == "abs" && o.Params.IsSimpleCsv())
144-
.ToList())
141+
// Constant math/trig functions => <the result>
142+
var mathOp = new List<Tuple<string, Func<double, double>>>
145143
{
146-
var x = absNode.Params.Children.Where(o => o.Token is FloatToken).Select(o => ((FloatToken)o.Token).Number).ToList();
147-
if (x.Count == 1)
148-
{
149-
absNode.Params.Remove();
150-
absNode.ReplaceWith(new GenericSyntaxNode(FloatToken.From(Math.Abs(x[0]), MaxDp)));
151-
didChange = true;
152-
}
153-
}
154-
155-
// sqrt(-1.1) => <the result>
156-
foreach (var sqrtNode in rootNode.TheTree
157-
.OfType<GlslFunctionCallSyntaxNode>()
158-
.Where(o => o.Name == "sqrt" && o.Params.IsSimpleCsv())
144+
new Tuple<string, Func<double, double>>("abs", Math.Abs),
145+
new Tuple<string, Func<double, double>>("sqrt", d => Math.Sqrt(Math.Abs(d))),
146+
new Tuple<string, Func<double, double>>("sin", Math.Sin),
147+
new Tuple<string, Func<double, double>>("cos", Math.Cos),
148+
new Tuple<string, Func<double, double>>("tan", Math.Tan),
149+
new Tuple<string, Func<double, double>>("asin", Math.Asin),
150+
new Tuple<string, Func<double, double>>("acos", Math.Acos),
151+
new Tuple<string, Func<double, double>>("atan", Math.Atan),
152+
new Tuple<string, Func<double, double>>("radians", x => x / 180.0 * Math.PI),
153+
new Tuple<string, Func<double, double>>("degrees", x => x / Math.PI * 180.0)
154+
};
155+
156+
foreach (var mathNode in functionCalls
157+
.Where(o => mathOp.Select(op => op.Item1).Contains(o.Name) && o.Params.IsSimpleCsv())
159158
.ToList())
160159
{
161-
var x = sqrtNode.Params.Children.Where(o => o.Token is FloatToken).Select(o => ((FloatToken)o.Token).Number).ToList();
160+
var x = mathNode.Params.Children.Where(o => o.Token is FloatToken).Select(o => ((FloatToken)o.Token).Number).ToList();
162161
if (x.Count == 1)
163162
{
164-
sqrtNode.Params.Remove();
165-
sqrtNode.ReplaceWith(new GenericSyntaxNode(FloatToken.From(Math.Sqrt(Math.Abs(x[0])), MaxDp)));
163+
mathNode.Params.Remove();
164+
var mathFunc = mathOp.Single(o => o.Item1 == mathNode.Name).Item2;
165+
mathNode.ReplaceWith(new GenericSyntaxNode(FloatToken.From(mathFunc(x[0]), MaxDp)));
166166
didChange = true;
167167
}
168168
}

ShaderShrinker/UnitTests/ShrinkerTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,37 @@ public void CheckArithmeticWitSqrtFunction(
16071607
Assert.That(rootNode.ToCode().ToSimple(), Is.EqualTo(expected));
16081608
}
16091609

1610+
[Test, Sequential]
1611+
public void CheckArithmeticWithTrigFunctions(
1612+
[Values("float f = sin(3.141);",
1613+
"float f = cos(0.5);",
1614+
"float f = tan(1.0);",
1615+
"float f = asin(1.0);",
1616+
"float f = acos(0.6);",
1617+
"float f = atan(1.0);",
1618+
"float f = radians(0.5);",
1619+
"float f = degrees(90.0);")] string code,
1620+
[Values("float f = 59e-5;",
1621+
"float f = .87758;",
1622+
"float f = 1.55741;",
1623+
"float f = 1.5708;",
1624+
"float f = .9273;",
1625+
"float f = .7854;",
1626+
"float f = .00873;",
1627+
"float f = 5156.6201;")] string expected)
1628+
{
1629+
var lexer = new Lexer();
1630+
lexer.Load(code);
1631+
1632+
var options = CustomOptions.None();
1633+
options.PerformArithmetic = true;
1634+
var rootNode = new Parser(lexer)
1635+
.Parse()
1636+
.Simplify(options);
1637+
1638+
Assert.That(rootNode.ToCode().ToSimple(), Is.EqualTo(expected));
1639+
}
1640+
16101641
[Test, Sequential]
16111642
public void CheckArithmeticWithVectorAndScalar(
16121643
[Values("vec2 f = vec2(1.1, 2.2) + 3.3;",

0 commit comments

Comments
 (0)