@thi.ng/shader-ast-optimize 0.3.32 → 0.3.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:04Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -4,211 +4,158 @@ import { deg, rad } from "@thi.ng/math/angle";
4
4
  import { clamp } from "@thi.ng/math/interval";
5
5
  import { mix } from "@thi.ng/math/mix";
6
6
  import { fract, mod } from "@thi.ng/math/prec";
7
- import { isFloat, isInt, isLitNumericConst, isLitVecConst, isUint, } from "@thi.ng/shader-ast/ast/checks";
7
+ import {
8
+ isFloat,
9
+ isInt,
10
+ isLitNumericConst,
11
+ isLitVecConst,
12
+ isUint
13
+ } from "@thi.ng/shader-ast/ast/checks";
8
14
  import { FLOAT0, float, int, lit, uint } from "@thi.ng/shader-ast/ast/lit";
9
15
  import { allChildren, walk } from "@thi.ng/shader-ast/ast/scope";
10
16
  import { LOGGER } from "@thi.ng/shader-ast/logger";
11
- /**
12
- * Replaces contents of `node` with those of `next`. All other existing props in
13
- * `node` will be removed.
14
- *
15
- * @param node -
16
- * @param next -
17
- *
18
- * @internal
19
- */
20
17
  const replaceNode = (node, next) => {
21
- if (LOGGER.level <= LogLevel.DEBUG) {
22
- LOGGER.debug(`replacing AST node:`);
23
- LOGGER.debug("\told: " + JSON.stringify(node));
24
- LOGGER.debug("\tnew: " + JSON.stringify(next));
25
- }
26
- for (let k in node) {
27
- !next.hasOwnProperty(k) && delete node[k];
28
- }
29
- Object.assign(node, next);
30
- return true;
18
+ if (LOGGER.level <= LogLevel.DEBUG) {
19
+ LOGGER.debug(`replacing AST node:`);
20
+ LOGGER.debug(" old: " + JSON.stringify(node));
21
+ LOGGER.debug(" new: " + JSON.stringify(next));
22
+ }
23
+ for (let k in node) {
24
+ !next.hasOwnProperty(k) && delete node[k];
25
+ }
26
+ Object.assign(node, next);
27
+ return true;
31
28
  };
32
29
  const replaceNumericNode = (node, res) => {
33
- node.type === "int" && (res |= 0);
34
- node.type === "uint" && (res >>>= 0);
35
- return replaceNode(node, lit(node.type, res));
30
+ node.type === "int" && (res |= 0);
31
+ node.type === "uint" && (res >>>= 0);
32
+ return replaceNode(node, lit(node.type, res));
36
33
  };
37
- /** @internal */
38
- const maybeFoldMath = (op, l, r) => op === "+"
39
- ? l + r
40
- : op === "-"
41
- ? l - r
42
- : op === "*"
43
- ? l * r
44
- : op === "/"
45
- ? l / r
46
- : undefined;
47
- /** @internal */
34
+ const maybeFoldMath = (op, l, r) => op === "+" ? l + r : op === "-" ? l - r : op === "*" ? l * r : op === "/" ? l / r : void 0;
48
35
  const COMPS = { x: 0, y: 1, z: 2, w: 3 };
49
36
  const BUILTINS = {
50
- abs: ([a]) => Math.abs(a),
51
- acos: ([a]) => Math.acos(a),
52
- asin: ([a]) => Math.asin(a),
53
- ceil: ([a]) => Math.ceil(a),
54
- clamp: ([a, b, c]) => clamp(a, b, c),
55
- cos: ([a]) => Math.cos(a),
56
- degrees: ([a]) => deg(a),
57
- exp: ([a]) => Math.exp(a),
58
- exp2: ([a]) => Math.pow(2, a),
59
- floor: ([a]) => Math.floor(a),
60
- fract: ([a]) => fract(a),
61
- inversesqrt: ([a]) => 1 / Math.sqrt(a),
62
- log: ([a]) => Math.log(a),
63
- log2: ([a]) => Math.log2(a),
64
- max: ([a, b]) => Math.max(a, b),
65
- min: ([a, b]) => Math.min(a, b),
66
- mix: ([a, b, c]) => mix(a, b, c),
67
- mod: ([a, b]) => mod(a, b),
68
- pow: ([a, b]) => Math.pow(a, b),
69
- radians: ([a]) => rad(a),
70
- sign: ([a]) => Math.sign(a),
71
- sin: ([a]) => Math.sin(a),
72
- tan: ([a]) => Math.tan(a),
73
- sqrt: ([a]) => Math.sqrt(a),
37
+ abs: ([a]) => Math.abs(a),
38
+ acos: ([a]) => Math.acos(a),
39
+ asin: ([a]) => Math.asin(a),
40
+ ceil: ([a]) => Math.ceil(a),
41
+ clamp: ([a, b, c]) => clamp(a, b, c),
42
+ cos: ([a]) => Math.cos(a),
43
+ degrees: ([a]) => deg(a),
44
+ exp: ([a]) => Math.exp(a),
45
+ exp2: ([a]) => Math.pow(2, a),
46
+ floor: ([a]) => Math.floor(a),
47
+ fract: ([a]) => fract(a),
48
+ inversesqrt: ([a]) => 1 / Math.sqrt(a),
49
+ log: ([a]) => Math.log(a),
50
+ log2: ([a]) => Math.log2(a),
51
+ max: ([a, b]) => Math.max(a, b),
52
+ min: ([a, b]) => Math.min(a, b),
53
+ mix: ([a, b, c]) => mix(a, b, c),
54
+ mod: ([a, b]) => mod(a, b),
55
+ pow: ([a, b]) => Math.pow(a, b),
56
+ radians: ([a]) => rad(a),
57
+ sign: ([a]) => Math.sign(a),
58
+ sin: ([a]) => Math.sin(a),
59
+ tan: ([a]) => Math.tan(a),
60
+ sqrt: ([a]) => Math.sqrt(a)
74
61
  };
75
- /** @internal */
76
- export const foldNode = defmulti((t) => t.tag, {}, {
62
+ const foldNode = defmulti(
63
+ (t) => t.tag,
64
+ {},
65
+ {
77
66
  [DEFAULT]: () => false,
78
67
  op1: (node) => {
79
- const $node = node;
80
- if ($node.op == "-" && isLitNumericConst($node.val)) {
81
- $node.val.val *= -1;
82
- return replaceNode(node, $node.val);
83
- }
68
+ const $node = node;
69
+ if ($node.op == "-" && isLitNumericConst($node.val)) {
70
+ $node.val.val *= -1;
71
+ return replaceNode(node, $node.val);
72
+ }
84
73
  },
85
74
  op2: (node) => {
86
- const $node = node;
87
- const op = $node.op;
88
- const l = $node.l;
89
- const r = $node.r;
90
- const isNumL = isLitNumericConst(l);
91
- const isNumR = isLitNumericConst(r);
92
- if (isNumL && isNumR) {
93
- let res = maybeFoldMath(op, l.val, r.val);
94
- if (res !== undefined)
95
- return replaceNumericNode(node, res);
96
- }
97
- else if (op === "*") {
98
- if ((isNumL && l.val === 0) || (isNumR && r.val === 0))
99
- return replaceNode(node, FLOAT0);
100
- if (isNumL && l.val === 1)
101
- return replaceNode(node, r);
102
- if (isNumR && r.val === 1)
103
- return replaceNode(node, l);
104
- }
105
- else if (op === "/") {
106
- if (isNumR && r.val === 1)
107
- return replaceNode(node, l);
108
- }
109
- else if (op === "+" || op === "-") {
110
- if (isNumL && l.val === 0)
111
- return replaceNode(node, r);
112
- if (isNumR && r.val === 0)
113
- return replaceNode(node, l);
114
- }
75
+ const $node = node;
76
+ const op = $node.op;
77
+ const l = $node.l;
78
+ const r = $node.r;
79
+ const isNumL = isLitNumericConst(l);
80
+ const isNumR = isLitNumericConst(r);
81
+ if (isNumL && isNumR) {
82
+ let res = maybeFoldMath(op, l.val, r.val);
83
+ if (res !== void 0)
84
+ return replaceNumericNode(node, res);
85
+ } else if (op === "*") {
86
+ if (isNumL && l.val === 0 || isNumR && r.val === 0)
87
+ return replaceNode(node, FLOAT0);
88
+ if (isNumL && l.val === 1)
89
+ return replaceNode(node, r);
90
+ if (isNumR && r.val === 1)
91
+ return replaceNode(node, l);
92
+ } else if (op === "/") {
93
+ if (isNumR && r.val === 1)
94
+ return replaceNode(node, l);
95
+ } else if (op === "+" || op === "-") {
96
+ if (isNumL && l.val === 0)
97
+ return replaceNode(node, r);
98
+ if (isNumR && r.val === 0)
99
+ return replaceNode(node, l);
100
+ }
115
101
  },
116
102
  call_i: (node) => {
117
- const $node = node;
118
- if ($node.args.every((x) => isLitNumericConst(x))) {
119
- const op = BUILTINS[$node.id];
120
- if (op !== undefined) {
121
- return replaceNumericNode(node, op($node.args.map((x) => x.val)));
122
- }
103
+ const $node = node;
104
+ if ($node.args.every((x) => isLitNumericConst(x))) {
105
+ const op = BUILTINS[$node.id];
106
+ if (op !== void 0) {
107
+ return replaceNumericNode(
108
+ node,
109
+ op($node.args.map((x) => x.val))
110
+ );
123
111
  }
112
+ }
124
113
  },
125
114
  lit: (node) => {
126
- const $node = node;
127
- if (isLitNumericConst($node.val)) {
128
- if (isFloat($node.val)) {
129
- return replaceNode(node, float($node.val.val));
130
- }
131
- if (isInt($node.val)) {
132
- return replaceNode(node, int($node.val.val));
133
- }
134
- if (isUint($node.val)) {
135
- return replaceNode(node, uint($node.val.val));
136
- }
115
+ const $node = node;
116
+ if (isLitNumericConst($node.val)) {
117
+ if (isFloat($node.val)) {
118
+ return replaceNode(node, float($node.val.val));
119
+ }
120
+ if (isInt($node.val)) {
121
+ return replaceNode(node, int($node.val.val));
122
+ }
123
+ if (isUint($node.val)) {
124
+ return replaceNode(node, uint($node.val.val));
137
125
  }
126
+ }
138
127
  },
139
128
  swizzle: (node) => {
140
- const $node = node;
141
- const val = $node.val;
142
- if (isLitVecConst(val)) {
143
- if (isFloat(node)) {
144
- return replaceNode(node, float(val.val[COMPS[$node.id]]));
145
- }
129
+ const $node = node;
130
+ const val = $node.val;
131
+ if (isLitVecConst(val)) {
132
+ if (isFloat(node)) {
133
+ return replaceNode(
134
+ node,
135
+ float(val.val[COMPS[$node.id]])
136
+ );
146
137
  }
147
- },
148
- });
149
- /**
150
- * Traverses given AST (potentially several times) and applies constant folding
151
- * optimizations where possible. Returns possibly updated tree (mutates
152
- * original).
153
- *
154
- * @remarks
155
- * Currently, only the following operations are supported / considered:
156
- *
157
- * - scalar math operators
158
- * - scalar math built-in functions
159
- * - single component vector swizzling
160
- * - literal hoisting
161
- *
162
- * @example
163
- * ```ts
164
- * const foo = defn("float", "foo", ["float"], (x) => [
165
- * ret(mul(x, add(neg(float(10)), float(42))))]
166
- * )
167
- *
168
- * const bar = vec2(100, 200);
169
- *
170
- * const prog = scope([
171
- * foo,
172
- * foo(add(float(1), float(2))),
173
- * foo(add($x(bar), $y(bar)))
174
- * ], true);
175
- *
176
- * // serialized (GLSL)
177
- * glsl(prog);
178
- *
179
- * // float foo(in float _sym0) {
180
- * // return (_sym0 * (-10.0 + 42.0));
181
- * // };
182
- * // foo((1.0 + 2.0));
183
- * // foo((vec2(100.0, 200.0).x + vec2(100.0, 200.0).y));
184
- *
185
- * // with constant folding
186
- * glsl(constantFolding(prog))
187
- *
188
- * // float foo(in float _sym0) {
189
- * // return (_sym0 * 32.0);
190
- * // };
191
- * // foo(3.0);
192
- * // foo(300.0);
193
- *
194
- * const expr = mul(float(4), $x(vec2(2)))
195
- *
196
- * glsl(expr)
197
- * // (4.0 * vec2(2.0).x)
198
- *
199
- * glsl(constantFolding(expr))
200
- * // 8.0
201
- * ```
202
- *
203
- * @param tree -
204
- */
205
- export const constantFolding = (tree) => {
206
- let exec = true;
207
- while (exec) {
208
- exec = false;
209
- walk((_, node) => {
210
- exec = foldNode(node) || exec;
211
- }, allChildren, null, tree, false);
138
+ }
212
139
  }
213
- return tree;
140
+ }
141
+ );
142
+ const constantFolding = (tree) => {
143
+ let exec = true;
144
+ while (exec) {
145
+ exec = false;
146
+ walk(
147
+ (_, node) => {
148
+ exec = foldNode(node) || exec;
149
+ },
150
+ allChildren,
151
+ null,
152
+ tree,
153
+ false
154
+ );
155
+ }
156
+ return tree;
157
+ };
158
+ export {
159
+ constantFolding,
160
+ foldNode
214
161
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/shader-ast-optimize",
3
- "version": "0.3.32",
3
+ "version": "0.3.33",
4
4
  "description": "Shader AST code optimization passes/strategies",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,14 +35,15 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.11",
37
- "@thi.ng/defmulti": "^3.0.9",
38
- "@thi.ng/logger": "^2.0.1",
39
- "@thi.ng/math": "^5.7.6",
40
- "@thi.ng/shader-ast": "^0.12.84"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/defmulti": "^3.0.10",
40
+ "@thi.ng/logger": "^2.0.2",
41
+ "@thi.ng/math": "^5.7.7",
42
+ "@thi.ng/shader-ast": "^0.12.85"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@microsoft/api-extractor": "^7.38.3",
46
+ "esbuild": "^0.19.8",
44
47
  "rimraf": "^5.0.5",
45
48
  "tools": "^0.0.1",
46
49
  "typedoc": "^0.25.4",
@@ -75,5 +78,5 @@
75
78
  "parent": "@thi.ng/shader-ast",
76
79
  "year": 2019
77
80
  },
78
- "gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n"
81
+ "gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
79
82
  }