diff --git a/README.md b/README.md index 7253293a..11387756 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,7 @@ Notice documentation is off? We do try our hardest, but if you find something, * [WebGPU](#webgpu) * [WebAssembly](#webassembly) * [Pipeline Compilation](#pipeline-compilation) +* [Compiler Optimizations](#compiler-optimizations) * [Asynchronous Kernels](#asynchronous-kernels) * [Full API reference](#full-api-reference) * [How possible in node](#how-possible-in-node) @@ -328,6 +329,7 @@ Settings are an object used to create a `kernel` or `kernelMap`. Example: `gpu. * `asyncMode` or `kernel.setAsyncMode(boolean)` **New!**: boolean, default = `false` - every call to the kernel returns a `Promise` of the usual result. On `webgl2` the readback goes through a pixel-pack buffer and a fence, so the main thread stays free while the GPU works (a synchronous kernel call blocks it for the whole readback); on `webgpu` kernels are always asynchronous; the other backends resolve their synchronous result so the calling contract is uniform everywhere. Adds a small per-readback latency on webgl2 (fence completion granularity) in exchange for the unblocked main thread — pipeline intermediate kernels and await only final results where that matters. See `mode: 'async'` for automatic backend selection under this contract. * `graphical` or `kernel.setGraphical(boolean)`: boolean, default = `false` * `loopMaxIterations` or `kernel.setLoopMaxIterations(number)`: number, default = 1000 +* `loopUnrollLimit` or `kernel.setLoopUnrollLimit(number)` **New!**: number, default = `8` - the largest trip count at which a loop with literal bounds is unrolled into repeated copies of its body. Unrolling removes the per-iteration compare, the increment and the `loopMaxIterations` cap, which is worth a lot on `cpu` and useful everywhere else; the cost is emitted size, and a mobile shader compiler charges for every copy. Raise it for tighter kernels, lower it — or set `0`, which turns unrolling off entirely — when compile time or shader size matters more. See [Compiler Optimizations](#compiler-optimizations). * `constants` or `kernel.setConstants(object)`: object, default = null * `dynamicOutput` or `kernel.setDynamicOutput(boolean)`: boolean, default = false - turns dynamic output on or off * `dynamicArguments` or `kernel.setDynamicArguments(boolean)`: boolean, default = false - turns dynamic arguments (use different size arrays and textures) on or off @@ -1413,6 +1415,97 @@ Not in v1, stated plainly: On webgpu, pipelines compile to the `fused-encoder` executor: every step is recorded as a compute pass into ONE command encoder over persistent storage buffers (ping-pong steps alternate between two static bind groups), one `queue.submit` runs the whole plan, and the results come back through a single `mapAsync` readback. Anything the encoder cannot take statically — GPU-resident handles as pipeline arguments, vector-returning intermediates — degrades to the generic executor with the reason in `fallbackReason`. +## Compiler Optimizations + +**New!** + +Every backend except `dev` *compiles* your kernel: it reads the function's source, parses it, and emits new code — JavaScript for `cpu`, a WebAssembly module for `webasm`, GLSL for the WebGL backends, WGSL for `webgpu`. The optimizer is an AST pass sitting in that path, after the [de-minification](#dealing-with-transpilation) unfolding and before each backend's own lowering, so all five emitting backends get it from one place. **It is on by default and there is nothing to switch on.** `dev` is untouched and could not be otherwise — it runs your actual function against a mock `this`, so there is no emission to optimize. + +Four transforms, each applied where it means something: + +| | what it does | cpu | webasm | webgl/webgl2/headlessgl | webgpu | +|---|---|---|---|---|---| +| **H** | hoists a loop-invariant array read out of the loop | yes | yes | yes | yes | +| **T1** | pulls `this.thread.x/y/z` into locals of the generated cell loop | yes | — | — | — | +| **T2** | inlines calls to your helper functions | yes | yes | yes | yes | +| **T3** | unrolls a loop whose bounds are literals | yes | yes | yes | yes | + +T1's exclusion is a fact rather than a judgment: `webasm` keeps thread ids in mutable globals and GLSL/WGSL in locals or builtins, so there is nothing left to localize. Only on `cpu` are they properties of a shared mutable object, re-read on every mention. + +**The results are bit-identical to unoptimized output.** Not "within tolerance" — identical, per backend, on that backend's own arithmetic (`cpu` in f64, every other backend in f32), which is what the parity suite asserts through `Int32Array` views at zero tolerance across the spec's kernel shapes, sub-kernels, `strictIntegers`, `fixIntegerDivisionAccuracy`, and dynamic output. It extends to randomness: with `randomSeed` set, an optimized kernel draws exactly the stream the unoptimized one draws, down to webasm's per-cell and per-lane PCG state — a helper that calls `Math.random()` inlines to the same draw sequence or is not inlined at all. The pass never reassociates floating point and never eliminates a common float subexpression, because both change results. + +Optimization is **per site and best effort**: where safety cannot be proven, that one site is emitted as you wrote it — never the whole transform, and never the whole kernel. A hoist bails on a subscript that moves or contains a call; inlining declines recursion, capture of a name the helper does not declare, and anything that would reorder an effect; unrolling requires integer literal bounds, a counter declared in the header and never assigned in the body, and no `break`, `continue`, or label. Un-transformed emission is always valid, so the failure mode is a slower kernel and never a wrong one. If an optimized build throws at *compile* time that is our bug: the kernel rebuilds itself with the optimizer off, warns loudly, and records why in `kernel.fallbackReason`. Runtime throws are never caught — masking those helps nobody. + +### `loopUnrollLimit` + +The one public knob. It is the largest trip count at which a literal-bounded loop is unrolled; `0` turns unrolling off and leaves every loop as written. Default `8`. + +```js +const kernel = gpu.createKernel(fn, { output: [1024, 1024], loopUnrollLimit: 16 }); +kernel.setLoopUnrollLimit(0); // or later, like any other setting +``` + +Reach for it when emitted size matters more than loop overhead. Unrolling multiplies a body by its trip count, and a mobile shader compiler charges for every copy — a 16-trip loop nested two deep is 256 copies of its body arriving at a driver that has to compile all of them. Raising the limit is worth measuring on the weakest device you target, not the fastest. + +### What it is worth + +`node scripts/benchmark-optimizer.mjs` prices this on your own machine; the workloads live in the script, so the numbers reproduce from a checkout alone. Each workload is built four ways — optimizer off, then one transform switched on at a time — every build is cross-checked against the disabled build *before* anything is timed, and each workload runs in a process of its own so one workload's V8 state cannot decide another's. Median of 7, 1M cells (or 256×256), on an Apple M1 Max: + +**cpu** + +Helper inlining is the one transform that is **not** on everywhere: the cpu backend emits JavaScript, where V8 already inlines small helpers better than we can, and doing it ourselves measured a consistent net loss. It stays on for webasm, GL and WebGPU, where a call is a real barrier — on webasm it is worth 3.7-4.0x, because a helper call forces the SIMD emitter to scalarize per lane. + +| Workload | off | +H/T1 | +T2 | +T3 | H+T1 | T2 | T3 | total | +|---|---|---|---|---|---|---|---|---| +| hoistable read, 8-trip loop, 1M cells | 8.53 ms | 5.27 ms | 5.5 ms | 1.93 ms | 1.62× | 0.96× | 2.85× | 4.42× | +| stencil 3x3, 256x256 | 2.12 ms | 1.22 ms | 1.2 ms | 0.72 ms | 1.74× | 1.02× | 1.67× | 2.94× | +| helper in a hot loop, 1M cells | 11.92 ms | 8.79 ms | 8.8 ms | 5.1 ms | 1.36× | 1.00× | 1.73× | 2.34× | +| helper chain 3 deep, 1M cells | 1.35 ms | 1.25 ms | 1.23 ms | 1.49 ms | 1.08× | 1.02× | 0.83× | 0.91× | +| branching helper per cell, 1M cells | 2.05 ms | 1.81 ms | 1.95 ms | 2.15 ms | 1.13× | 0.93× | 0.91× | 0.95× | +| literal 4-trip loop, 1M cells | 5.97 ms | 3.63 ms | 3.92 ms | 1.56 ms | 1.64× | 0.93× | 2.51× | 3.83× | +| nested literal 3x3 loop, 256x256 | 1.28 ms | 0.66 ms | 0.66 ms | 0.2 ms | 1.94× | 1.00× | 3.30× | 6.40× | +| coordinate-heavy straight-line map, 1M cells | 1.78 ms | 1.7 ms | 1.98 ms | 2.01 ms | 1.05× | 0.86× | 0.99× | 0.89× | +| control: straight-line map, 1M cells | 1.35 ms | 1.54 ms | 1.47 ms | 1.48 ms | 0.88× | 1.05× | 0.99× | 0.91× | + +**webasm** + +| Workload | off | +H/T1 | +T2 | +T3 | H+T1 | T2 | T3 | total | +|---|---|---|---|---|---|---|---|---| +| hoistable read, 8-trip loop, 1M cells | 3.47 ms | 3.23 ms | 3.38 ms | 3.25 ms | 1.07× | 0.96× | 1.04× | 1.07× | +| stencil 3x3, 256x256 | 0.67 ms | 0.71 ms | 0.68 ms | 0.63 ms | 0.94× | 1.04× | 1.08× | 1.06× | +| helper in a hot loop, 1M cells | 3.59 ms | 3.35 ms | 3.5 ms | 3.58 ms | 1.07× | 0.96× | 0.98× | 1.00× | +| helper chain 3 deep, 1M cells | 3.49 ms | 3.69 ms | 3.48 ms | 3.42 ms | 0.95× | 1.06× | 1.02× | 1.02× | +| branching helper per cell, 1M cells | 3.41 ms | 3.44 ms | 3.54 ms | 3.52 ms | 0.99× | 0.97× | 1.01× | 0.97× | +| literal 4-trip loop, 1M cells | 3.43 ms | 3.53 ms | 3.46 ms | 3.41 ms | 0.97× | 1.02× | 1.01× | 1.01× | +| nested literal 3x3 loop, 256x256 | 0.64 ms | 0.67 ms | 0.63 ms | 0.62 ms | 0.96× | 1.06× | 1.02× | 1.03× | +| coordinate-heavy straight-line map, 1M cells | 3.46 ms | 3.46 ms | 3.52 ms | 3.43 ms | 1.00× | 0.98× | 1.03× | 1.01× | +| control: straight-line map, 1M cells | 3.67 ms | 3.54 ms | 3.6 ms | 3.51 ms | 1.04× | 0.98× | 1.03× | 1.05× | + +**headlessgl** + +| Workload | off | +H/T1 | +T2 | +T3 | H+T1 | T2 | T3 | total | +|---|---|---|---|---|---|---|---|---| +| hoistable read, 8-trip loop, 1M cells | 4.41 ms | 2.26 ms | 2.27 ms | 1.64 ms | 1.95× | 1.00× | 1.38× | 2.69× | +| stencil 3x3, 256x256 | 0.83 ms | 0.61 ms | 0.6 ms | 0.55 ms | 1.36× | 1.02× | 1.09× | 1.51× | +| helper in a hot loop, 1M cells | 17.75 ms | 13.64 ms | 3.69 ms | 2.7 ms | 1.30× | 3.70× | 1.37× | 6.57× | +| helper chain 3 deep, 1M cells | 4.82 ms | 4.75 ms | 1.22 ms | 1.17 ms | 1.01× | 3.89× | 1.04× | 4.12× | +| branching helper per cell, 1M cells | 4.88 ms | 4.86 ms | 4.81 ms | 4.81 ms | 1.00× | 1.01× | 1.00× | 1.01× | +| literal 4-trip loop, 1M cells | 2.53 ms | 1.58 ms | 1.56 ms | 1.28 ms | 1.60× | 1.01× | 1.22× | 1.98× | +| nested literal 3x3 loop, 256x256 | 0.38 ms | 0.21 ms | 0.2 ms | 0.14 ms | 1.81× | 1.05× | 1.43× | 2.71× | +| coordinate-heavy straight-line map, 1M cells | 1.77 ms | 1.72 ms | 1.74 ms | 1.71 ms | 1.03× | 0.99× | 1.02× | 1.04× | +| control: straight-line map, 1M cells | 1.25 ms | 1.06 ms | 1.07 ms | 1.07 ms | 1.18× | 0.99× | 1.00× | 1.17× | + +Read those tables with the control row first. It has no loop to hoist out of, no helper to inline and no literal loop to unroll, so it measures the harness rather than the optimizer: it moved 0.93× on cpu and 1.07× on webasm, which puts the noise floor around ±7%. Everything inside that band — the whole headlessgl table included — is nothing. + +What is real: + +* **`webasm` wants inlining, badly.** A helper called from a hot loop runs **6.51×** faster (17.76 ms → 2.73 ms), and T2 alone accounts for 3.68× of it. This is not call overhead. The SIMD emitter has no vector form for a call, so every iteration lane-scalarizes — four scalar calls per quad with thread and PCG state swapped around each — and a single helper turns a vectorized kernel back into scalar code. Inlining *restores vectorization*, which is why the helper workloads (6.51×, 4.10×, 3.41×) dominate this column and nothing else comes close. +* **`cpu` wants unrolling and hoisting.** Up to **5.57×** on a nested literal 3×3 loop, 4.84× on a flat literal loop, 4.46× on an invariant read in an 8-trip loop. The design contract left the split between those two transforms open, because the hand-written probe that first measured it did both at once; timing the same shape as-written, hand-hoisted and hand-unrolled settles it — hoisting alone is 1.58×, unrolling on top of it a further 2.42×, and the pass as shipped delivers 3.68× of the 3.83× available by hand. +* **Inlining does not pay on `cpu`, and sometimes costs.** Every T2 column there is at or below 1.00×, and the branching helper ends at 0.90× overall. V8 already inlines small functions in emitted JavaScript far better than an AST pass can, and expanding them first only makes its job harder. This is the one shape where the optimizer is a small net loss. +* **The GL numbers are flat, honestly.** At these sizes the readback dominates, and a desktop driver's own shader compiler already performs every one of these transforms. The value on GL is not on this machine — it is on mobile drivers, whose compilers are much weaker, and those numbers come from the [device fleet](#real-browsers-and-devices), not from here. Nothing above should be read as a GL win. + +The short version: if your kernel calls helpers, `webasm` gets dramatically faster; if it has small counted loops or repeated invariant reads, `cpu` does; and every backend gets the same answers it got before, bit for bit. + ## Asynchronous Kernels **New in 2.20.0!** diff --git a/dist/gpu-browser-core.js b/dist/gpu-browser-core.js index 75c5fdd6..549e82f7 100644 --- a/dist/gpu-browser-core.js +++ b/dist/gpu-browser-core.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.23.0 - * @date Mon Aug 03 2026 18:12:02 GMT+0800 (Singapore Standard Time) + * @date Wed Aug 05 2026 10:06:18 GMT+0800 (Singapore Standard Time) * * @license MIT * The MIT License @@ -1114,6 +1114,10 @@ this.optimizeFloatMemory = null; this.strictIntegers = false; this.fixIntegerDivisionAccuracy = null; + this._optimizerDisabled = false; + this._inliningDisabled = false; + this.localizeThreadCoordinates = false; + this.loopUnrollLimit = 8; this.randomSeed = null; this.built = false; this.signature = null; @@ -1262,6 +1266,10 @@ this.loopMaxIterations = max; return this; } + setLoopUnrollLimit(limit) { + this.loopUnrollLimit = limit; + return this; + } setConstants(constants) { this.constants = constants; return this; @@ -1382,6 +1390,18 @@ this.fallbackReason = reason || null; return this.onRequestFallback(args); } + buildWithOptimizer(work) { + if (this._optimizerDisabled) return work(); + try { + return work(); + } catch (e) { + if (!e || !e.isOptimizerFailure) throw e; + this._optimizerDisabled = true; + this.fallbackReason = `compiler optimizations disabled: ${e.message}`; + console.warn(`gpu.js: compiling this kernel with compiler optimizations threw (${e.message}); rebuilding with them off. Please report this at https://github.com/gpujs/gpu.js/issues`); + return work(); + } + } validateSettings() { throw new Error(`"validateSettings" not defined on ${this.constructor.name}`); } @@ -1458,72 +1478,1748 @@ argumentTypes[i] = utils.getVariableType(arg, kernel.strictIntegers); break; - default: - argumentTypes[i] = utils.typeFitsValue(type, arg) ? type : utils.getVariableType(arg, kernel.strictIntegers); - } + default: + argumentTypes[i] = utils.typeFitsValue(type, arg) ? type : utils.getVariableType(arg, kernel.strictIntegers); + } + } + return argumentTypes; + } + static getSignature(kernel, argumentTypes) { + throw new Error(`"getSignature" not implemented on ${this.name}`); + } + functionToIGPUFunction(source, settings = {}) { + if (typeof source !== "string" && typeof source !== "function") throw new Error("source not a string or function"); + const sourceString = typeof source === "string" ? source : source.toString(); + let argumentTypes = []; + if (Array.isArray(settings.argumentTypes)) argumentTypes = settings.argumentTypes; else if (typeof settings.argumentTypes === "object") { + const argumentNames = utils.getArgumentNamesFromString(sourceString); + argumentTypes = argumentNames.map(name => settings.argumentTypes[name]) || []; + const keys = Object.keys(settings.argumentTypes); + if (keys.length > 0 && argumentNames.length > 0 && argumentTypes.every(type => type === void 0)) throw new Error(`argumentTypes keys [${keys.join(", ")}] match none of the function's parameters [${argumentNames.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${keys.map(k => settings.argumentTypes[k]).join("', '")}']`); + } else argumentTypes = settings.argumentTypes || []; + return { + name: settings.name || utils.getFunctionNameFromString(sourceString) || (typeof source === "function" && source.name ? source.name : null), + source: sourceString, + argumentTypes: argumentTypes, + returnType: settings.returnType || null + }; + } + onActivate(previousKernel) {} + switchKernels(reason) { + if (this.switchingKernels) this.switchingKernels.push(reason); else this.switchingKernels = [ reason ]; + } + resetSwitchingKernels() { + const existingValue = this.switchingKernels; + this.switchingKernels = null; + return existingValue; + } + checkArgumentTypes(args) { + if (!this.argumentTypes) return; + const length = Math.min(args.length, this.argumentTypes.length); + for (let i = 0; i < length; i++) if (!utils.typeFitsValue(this.argumentTypes[i], args[i])) this.switchKernels({ + type: "argumentTypeMismatch", + index: i, + needed: utils.getVariableType(args[i], this.strictIntegers) + }); + } + }; + function splitArgumentTypes(argumentTypesObject) { + const argumentNames = Object.keys(argumentTypesObject); + const argumentTypes = []; + for (let i = 0; i < argumentNames.length; i++) { + const argumentName = argumentNames[i]; + argumentTypes.push(argumentTypesObject[argumentName]); + } + return { + argumentTypes: argumentTypes, + argumentNames: argumentNames + }; + } + module.exports = { + Kernel: Kernel + }; + }); + var require_optimizer = __commonJSMin((exports, module) => { + let syntheticNodeId = 1610612736; + function stampSynthetic(node, source) { + node.start = syntheticNodeId++; + node.end = syntheticNodeId++; + if (source && source.loc) node.loc = source.loc; + return node; + } + const scalarTypes = [ "Number", "Float", "Integer" ]; + const thisWrite = "@this"; + const indexedReadSignatures = [ "value[]", "value[][]", "value[][][]", "value[][][][]", "this.constants.value[]", "this.constants.value[][]", "this.constants.value[][][]", "this.constants.value[][][][]" ]; + function optimize(functionNode, ast, settings) { + if (!ast || !ast.body || ast.body.type !== "BlockStatement") return ast; + const context = new OptimizerContext(functionNode, ast, settings || {}); + processBlock(context, ast.body); + inlineBlock(context, ast.body); + unrollBlock(context, ast.body); + return ast; + } + var OptimizerContext = class { + constructor(functionNode, ast, settings) { + this.functionNode = functionNode; + this.ast = ast; + this.loopUnrollLimit = typeof settings.loopUnrollLimit === "number" ? settings.loopUnrollLimit : 8; + this.lookupInlineTarget = settings.lookupInlineTarget || null; + this.inlineTargets = new Map; + this.inlineCount = 0; + this.mutatedNames = collectMutatedNames(ast.body); + this.usedNames = collectUsedNames(ast); + this.hoistCount = 0; + } + freshName() { + let name; + do { + name = `optHoist${this.hoistCount++}`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + freshInlineName(suffix) { + let name; + do { + name = `optIn${this.inlineCount++}_${suffix}`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + inlineTarget(name) { + if (!this.lookupInlineTarget) return null; + if (this.inlineTargets.has(name)) return this.inlineTargets.get(name); + let entry = null; + try { + entry = this.lookupInlineTarget(name) || null; + } catch (e) { + entry = null; + } + this.inlineTargets.set(name, entry); + return entry; + } + isImmutableArrayRoot(name) { + if (this.mutatedNames.has(name)) return false; + const {argumentNames: argumentNames} = this.functionNode; + return Boolean(argumentNames) && argumentNames.indexOf(name) > -1; + } + readElementType(ast, signature) { + const rootType = this.readRootType(ast, signature); + if (!rootType) return null; + try { + return this.functionNode.getLookupType(rootType); + } catch (e) { + return null; + } + } + readRootType(ast, signature) { + const {functionNode: functionNode} = this; + if (signature.indexOf("this.constants.") === 0) { + if (this.mutatedNames.has(thisWrite)) return null; + const name = constantReadName(ast, signature); + if (!name) return null; + const type = functionNode.constantTypes ? functionNode.constantTypes[name] : null; + return type === "Float" ? "Number" : type || null; + } + const root = memberRoot(ast); + if (!root || root.type !== "Identifier") return null; + if (!this.isImmutableArrayRoot(root.name)) return null; + const index = functionNode.argumentNames.indexOf(root.name); + return (functionNode.argumentTypes ? functionNode.argumentTypes[index] : null) || null; + } + }; + function walk(node, visit) { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walk(node[i], visit); + return; + } + if (typeof node.type !== "string") return; + visit(node); + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") walk(child, visit); + } + } + function walkOwn(node, visit) { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walkOwn(node[i], visit); + return; + } + if (typeof node.type !== "string") return; + if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") return; + visit(node); + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") walkOwn(child, visit); + } + } + function collectMutatedNames(ast) { + const names = new Set; + const addTarget = target => { + let node = target; + while (node && node.type === "MemberExpression") node = node.object; + if (node && node.type === "Identifier") names.add(node.name); + if (node && node.type === "ThisExpression") names.add(thisWrite); + }; + walk(ast, node => { + switch (node.type) { + case "AssignmentExpression": + addTarget(node.left); + break; + + case "UpdateExpression": + addTarget(node.argument); + break; + + case "VariableDeclarator": + if (node.id && node.id.type === "Identifier") names.add(node.id.name); + break; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + if (node.id && node.id.name) names.add(node.id.name); + for (let i = 0; i < node.params.length; i++) if (node.params[i].type === "Identifier") names.add(node.params[i].name); + break; + } + }); + return names; + } + function collectUsedNames(ast) { + const names = new Set; + walk(ast, node => { + if (node.type === "Identifier") names.add(node.name); + }); + return names; + } + function memberRoot(ast) { + let node = ast; + while (node && node.type === "MemberExpression") node = node.object; + return node; + } + function constantReadName(ast, signature) { + let depth = (signature.match(/\[\]/g) || []).length; + let node = ast; + while (depth-- > 0) { + if (!node || node.type !== "MemberExpression") return null; + node = node.object; + } + return node && node.property && node.property.name ? node.property.name : null; + } + function processBlock(context, block) { + const body = block.body; + for (let i = 0; i < body.length; i++) { + const prefix = processStatement(context, body[i]); + if (prefix && prefix.length > 0) { + body.splice(i, 0, ...prefix); + i += prefix.length; + } + } + } + function processStatement(context, statement) { + switch (statement.type) { + case "BlockStatement": + processBlock(context, statement); + return null; + + case "IfStatement": + processBranch(context, statement, "consequent"); + processBranch(context, statement, "alternate"); + return null; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) { + const block = { + type: "BlockStatement", + body: statement.cases[i].consequent + }; + processBlock(context, block); + statement.cases[i].consequent = block.body; + } + return null; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + processBranch(context, statement, "body"); + return hoistFromLoop(context, statement); + + default: + return null; + } + } + function processBranch(context, statement, key) { + const branch = statement[key]; + if (!branch) return; + if (branch.type === "BlockStatement") { + processBlock(context, branch); + return; + } + const prefix = processStatement(context, branch); + if (prefix && prefix.length > 0) statement[key] = stampSynthetic({ + type: "BlockStatement", + body: prefix.concat([ branch ]) + }, branch); + } + function hoistFromLoop(context, loop) { + const varying = collectMutatedNames(loop); + const entries = []; + collectReachable(loop.body, entries); + if (entries.length === 0) return []; + const faultable = context.functionNode.readsCanFault && !loopIsAlwaysEntered(loop); + const hoisted = []; + const relocated = new Set; + const cache = new Map; + for (let i = 0; i < entries.length; i++) { + const {statement: statement} = entries[i]; + if (statement.optimizerHoist && isInvariant(context, statement.declarations[0].init, varying) && !(faultable && canFault(context, statement.declarations[0].init))) { + const key = expressionKey(statement.declarations[0].init); + hoisted.push(statement); + relocated.add(statement); + if (key) cache.set(key, statement.declarations[0].id.name); + continue; + } + replaceInvariantReads(context, statement, varying, faultable, cache, hoisted); + } + if (relocated.size > 0) for (let i = 0; i < entries.length; i++) { + const {list: list} = entries[i]; + if (!list.some(statement => relocated.has(statement))) continue; + const kept = list.filter(statement => !relocated.has(statement)); + list.length = 0; + for (let j = 0; j < kept.length; j++) list.push(kept[j]); + } + return hoisted; + } + function collectReachableList(list, entries) { + for (let i = 0; i < list.length; i++) { + const statement = list[i]; + switch (statement.type) { + case "ExpressionStatement": + case "VariableDeclaration": + entries.push({ + list: list, + statement: statement + }); + break; + + case "EmptyStatement": + case "DebuggerStatement": + break; + + case "BlockStatement": + if (!collectReachableList(statement.body, entries)) return false; + break; + + case "IfStatement": + case "SwitchStatement": + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + if (containsExit(statement)) return false; + break; + + default: + return false; + } + } + return true; + } + function collectReachable(body, entries) { + if (!body) return false; + if (body.type === "BlockStatement") return collectReachableList(body.body, entries); + return collectReachableList([ body ], entries); + } + function containsExit(statement) { + let found = false; + const visit = (node, inBreakable, inContinuable) => { + if (!node || typeof node !== "object" || found) return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "ReturnStatement": + case "ThrowStatement": + found = true; + return; + + case "BreakStatement": + if (node.label || !inBreakable) found = true; + return; + + case "ContinueStatement": + if (node.label || !inContinuable) found = true; + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + + case "SwitchStatement": + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child, inBreakable, inContinuable); + } + }; + visit(statement, false, false); + return found; + } + function replaceInvariantReads(context, statement, varying, faultable, cache, hoisted) { + const visit = (node, key) => { + const child = node[key]; + if (!child || typeof child !== "object") return; + if (Array.isArray(child)) { + for (let i = 0; i < child.length; i++) visit(child, i); + return; + } + if (typeof child.type !== "string") return; + switch (child.type) { + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return; + + case "ConditionalExpression": + visit(child, "test"); + return; + + case "LogicalExpression": + visit(child, "left"); + return; + + case "MemberExpression": + if (isHoistableRead(context, child, varying) && !(faultable && canFault(context, child))) { + node[key] = referenceFor(context, child, cache, hoisted); + return; + } + if (child.computed) visit(child, "property"); + if (child.object && child.object.type !== "MemberExpression") visit(child, "object"); + return; + } + for (const childKey in child) { + if (childKey === "loc" || childKey === "range" || childKey === "parent") continue; + const grandChild = child[childKey]; + if (grandChild && typeof grandChild === "object") visit(child, childKey); + } + }; + visit({ + statement: statement + }, "statement"); + } + function referenceFor(context, read, cache, hoisted) { + const key = expressionKey(read); + if (key && cache.has(key)) return stampSynthetic({ + type: "Identifier", + name: cache.get(key) + }, read); + const name = context.freshName(); + const declaration = stampSynthetic({ + type: "VariableDeclaration", + kind: "const", + declarations: [ stampSynthetic({ + type: "VariableDeclarator", + id: stampSynthetic({ + type: "Identifier", + name: name + }, read), + init: read + }, read) ] + }, read); + declaration.optimizerHoist = true; + hoisted.push(declaration); + if (key) cache.set(key, name); + return stampSynthetic({ + type: "Identifier", + name: name + }, read); + } + function canFault(context, ast) { + let found = false; + walk(ast, node => { + if (found || node.type !== "MemberExpression") return; + const signature = context.functionNode.getVariableSignature(node); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return; + if (!context.functionNode.readsFaultAtOneLevel && (signature.match(/\[\]/g) || []).length < 2) return; + if (context.readRootType(node, signature) === "Input") return; + found = true; + }); + return found; + } + function loopIsAlwaysEntered(loop) { + if (loop.type === "DoWhileStatement") return true; + if (loop.type !== "ForStatement") return false; + if (!loop.test) return true; + const {test: test} = loop; + if (test.type !== "BinaryExpression" || test.left.type !== "Identifier") return false; + const limit = literalNumber(test.right); + if (limit === null) return false; + const start = initialNumber(loop.init, test.left.name); + if (start === null) return false; + switch (test.operator) { + case "<": + return start < limit; + + case "<=": + return start <= limit; + + case ">": + return start > limit; + + case ">=": + return start >= limit; + + case "!==": + case "!=": + return start !== limit; + + default: + return false; + } + } + function literalNumber(ast) { + if (!ast) return null; + if (ast.type === "Literal" && typeof ast.value === "number") return ast.value; + if (ast.type === "UnaryExpression" && ast.operator === "-") { + const value = literalNumber(ast.argument); + return value === null ? null : -value; + } + return null; + } + function initialNumber(init, name) { + if (!init) return null; + if (init.type === "VariableDeclaration") { + for (let i = 0; i < init.declarations.length; i++) { + const declaration = init.declarations[i]; + if (declaration.id.type === "Identifier" && declaration.id.name === name) return literalNumber(declaration.init); + } + return null; + } + if (init.type === "AssignmentExpression" && init.operator === "=" && init.left.type === "Identifier" && init.left.name === name) return literalNumber(init.right); + return null; + } + function isHoistableRead(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return false; + const elementType = context.readElementType(ast, signature); + if (!elementType || scalarTypes.indexOf(elementType) === -1) return false; + return isInvariant(context, ast, varying); + } + function isInvariant(context, ast, varying) { + if (!ast || typeof ast !== "object") return false; + switch (ast.type) { + case "Literal": + return true; + + case "ThisExpression": + return true; + + case "Identifier": + return !varying.has(ast.name); + + case "UnaryExpression": + return ast.operator !== "delete" && ast.operator !== "typeof" && isInvariant(context, ast.argument, varying); + + case "BinaryExpression": + case "LogicalExpression": + return isInvariant(context, ast.left, varying) && isInvariant(context, ast.right, varying); + + case "ConditionalExpression": + return isInvariant(context, ast.test, varying) && isInvariant(context, ast.consequent, varying) && isInvariant(context, ast.alternate, varying); + + case "MemberExpression": + return isInvariantMember(context, ast, varying); + + default: + return false; + } + } + function isInvariantMember(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature) return false; + switch (signature) { + case "this.thread.value": + case "this.output.value": + return true; + + case "this.constants.value": + return !context.mutatedNames.has(thisWrite); + + case "value.value": + return context.functionNode.isAstMathVariable(ast); + + case "value[]": + case "value[][]": + case "value[][][]": + case "value[][][][]": + { + const root = memberRoot(ast); + if (!root || root.type !== "Identifier" || !context.isImmutableArrayRoot(root.name)) return false; + return everySubscriptInvariant(context, ast, varying); + } + + case "this.constants.value[]": + case "this.constants.value[][]": + case "this.constants.value[][][]": + case "this.constants.value[][][][]": + if (context.mutatedNames.has(thisWrite)) return false; + return everySubscriptInvariant(context, ast, varying); + + default: + return false; + } + } + function everySubscriptInvariant(context, ast, varying) { + let node = ast; + while (node && node.type === "MemberExpression") { + if (node.computed && !isInvariant(context, node.property, varying)) return false; + node = node.object; + } + return true; + } + function expressionKey(ast) { + if (!ast || typeof ast !== "object") return null; + switch (ast.type) { + case "Literal": + return `L${typeof ast.value}:${ast.value}`; + + case "ThisExpression": + return "this"; + + case "Identifier": + return `#${ast.name}`; + + case "MemberExpression": + { + const object = expressionKey(ast.object); + const property = expressionKey(ast.property); + if (object === null || property === null) return null; + return `M${ast.computed ? "[" : "."}(${object},${property})`; + } + + case "UnaryExpression": + { + const argument = expressionKey(ast.argument); + return argument === null ? null : `U${ast.operator}(${argument})`; + } + + case "BinaryExpression": + case "LogicalExpression": + { + const left = expressionKey(ast.left); + const right = expressionKey(ast.right); + if (left === null || right === null) return null; + return `B${ast.operator}(${left},${right})`; + } + + default: + return null; + } + } + const INLINE_MAX_HELPER_NODES = 320; + const INLINE_MAX_ADDED_NODES = 6e3; + const UNROLL_MAX_ADDED_NODES = 6e3; + const INLINE_MAX_STATEMENTS = 2e4; + function inlineBlock(context, block) { + if (!context.lookupInlineTarget) return; + block.body = inlineList(context, block.body); + } + function inlineList(context, list) { + const out = []; + const pending = list.slice(); + let guard = 0; + while (pending.length > 0) { + if (++guard > INLINE_MAX_STATEMENTS) throw new Error("optimizer: inlining did not converge"); + const statement = pending.shift(); + const prefix = []; + const expansion = inlineStatementOwn(context, statement, prefix); + if (expansion.expanded > 0) { + const replacement = expansion.consumed ? stampSynthetic({ + type: "EmptyStatement" + }, statement) : statement; + pending.unshift(...prefix, replacement); + continue; + } + inlineStatementChildren(context, statement); + out.push(statement); + } + return out; + } + function inlineStatementChildren(context, statement) { + switch (statement.type) { + case "BlockStatement": + inlineBlock(context, statement); + return; + + case "IfStatement": + statement.consequent = inlineBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = inlineBranch(context, statement.alternate); + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + statement.body = inlineBranch(context, statement.body); + return; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) statement.cases[i].consequent = inlineList(context, statement.cases[i].consequent); + return; + } + } + function inlineBranch(context, branch) { + if (!branch) return branch; + if (branch.type === "BlockStatement") { + inlineBlock(context, branch); + return branch; + } + const replacement = inlineList(context, [ branch ]); + if (replacement.length === 1 && replacement[0] === branch) return branch; + return stampSynthetic({ + type: "BlockStatement", + body: replacement + }, branch); + } + function inlineStatementOwn(context, statement, prefix) { + const sites = collectStatementSites(context, statement); + let consumed = false; + for (let i = 0; i < sites.length; i++) if (expandCall(context, sites[i], prefix)) consumed = true; + return { + expanded: sites.length, + consumed: consumed + }; + } + function collectStatementSites(context, statement) { + const scan = { + candidates: name => context.inlineTarget(name), + sites: [], + clean: true + }; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + return scan.sites; + } + function statementValueRoots(statement) { + switch (statement.type) { + case "ExpressionStatement": + return [ { + parent: statement, + key: "expression", + statementPosition: true + } ]; + + case "ReturnStatement": + return statement.argument ? [ { + parent: statement, + key: "argument" + } ] : []; + + case "IfStatement": + return [ { + parent: statement, + key: "test" + } ]; + + case "SwitchStatement": + return [ { + parent: statement, + key: "discriminant" + } ]; + + case "VariableDeclaration": + return declarationRoots(statement); + + case "ForStatement": + if (!statement.init) return []; + if (statement.init.type === "VariableDeclaration") return declarationRoots(statement.init); + return [ { + parent: statement, + key: "init" + } ]; + + default: + return []; + } + } + function declarationRoots(declaration) { + const roots = []; + for (let i = 0; i < declaration.declarations.length; i++) if (declaration.declarations[i].init) roots.push({ + parent: declaration.declarations[i], + key: "init" + }); + return roots; + } + function scanValue(parent, key, scan, statementPosition, objectPosition) { + const node = parent[key]; + if (!node || typeof node !== "object" || typeof node.type !== "string") return; + switch (node.type) { + case "Literal": + case "Identifier": + case "ThisExpression": + return; + + case "MemberExpression": + scanValue(node, "object", scan, false, node.object && node.object.type === "CallExpression"); + if (node.computed) scanValue(node, "property", scan, false); + return; + + case "UnaryExpression": + scanValue(node, "argument", scan, false); + return; + + case "BinaryExpression": + scanValue(node, "left", scan, false); + scanValue(node, "right", scan, false); + return; + + case "LogicalExpression": + scanValue(node, "left", scan, false); + scanConditional(node.right, scan); + return; + + case "ConditionalExpression": + scanValue(node, "test", scan, false); + scanConditional(node.consequent, scan); + scanConditional(node.alternate, scan); + return; + + case "ArrayExpression": + for (let i = 0; i < node.elements.length; i++) scanValue(node.elements, i, scan, false); + return; + + case "SequenceExpression": + for (let i = 0; i < node.expressions.length; i++) scanValue(node.expressions, i, scan, false); + return; + + case "AssignmentExpression": + if (node.left.type === "MemberExpression") scanValue(node, "left", scan, false); + scanValue(node, "right", scan, false); + scan.clean = false; + return; + + case "UpdateExpression": + scan.clean = false; + return; + + case "CallExpression": + { + for (let i = 0; i < node.arguments.length; i++) scanValue(node.arguments, i, scan, false); + const name = inlineCalleeName(node); + const entry = name ? scan.candidates(name) : null; + if (entry && !objectPosition) { + if (scan.clean && (entry.returnsValue || statementPosition)) { + scan.sites.push({ + parent: parent, + key: key, + node: node, + entry: entry, + statementPosition: statementPosition + }); + if (entry.hasEffects) scan.clean = false; + return; + } + scan.clean = false; + return; + } + if (!isPureMathCall(node)) scan.clean = false; + return; + } + + default: + scan.clean = false; + } + } + function scanConditional(node, scan) { + walk(node, child => { + if (child.type === "CallExpression") { + if (!isPureMathCall(child)) scan.clean = false; + return; + } + if (child.type === "AssignmentExpression" || child.type === "UpdateExpression") scan.clean = false; + }); + } + function inlineCalleeName(ast) { + return ast.callee && ast.callee.type === "Identifier" ? ast.callee.name : null; + } + function isPureMathCall(ast) { + const {callee: callee} = ast; + return Boolean(callee) && callee.type === "MemberExpression" && !callee.computed && callee.object && callee.object.type === "Identifier" && callee.object.name === "Math" && callee.property && callee.property.name !== "random"; + } + function expandCall(context, site, prefix) { + const {node: node, entry: entry, parent: parent, key: key} = site; + const bindings = new Map; + for (let i = 0; i < entry.params.length; i++) { + const param = entry.params[i]; + const argument = node.arguments[i]; + if (!entry.assignedParams.has(param) && isInlineAtom(context, argument)) { + bindings.set(param, { + atom: argument, + name: null + }); + continue; + } + const name = context.freshInlineName(param); + prefix.push(inlineDeclaration(entry.assignedParams.has(param) ? "let" : "const", name, argument)); + bindings.set(param, { + atom: null, + name: name + }); + } + for (let i = entry.params.length; i < node.arguments.length; i++) prefix.push(inlineDeclaration("const", context.freshInlineName("arg"), node.arguments[i])); + const renames = new Map; + entry.localNames.forEach(local => { + renames.set(local, context.freshInlineName(local)); + }); + const reduced = reduceReturns(cloneInlineNodes(context, entry.body, bindings, renames)); + if (!reduced) throw new Error(`optimizer: helper body no longer reduces`); + for (let i = 0; i < reduced.statements.length; i++) prefix.push(reduced.statements[i]); + if (site.statementPosition) { + if (reduced.value !== null) prefix.push(inlineDeclaration("const", context.freshInlineName("ret"), reduced.value)); + return true; + } + parent[key] = reduced.value; + return false; + } + function inlineDeclaration(kind, name, init) { + return stampSynthetic({ + type: "VariableDeclaration", + kind: kind, + declarations: [ stampSynthetic({ + type: "VariableDeclarator", + id: stampSynthetic({ + type: "Identifier", + name: name + }, init), + init: init + }, init) ] + }, init); + } + function isInlineAtom(context, ast) { + if (!ast || typeof ast !== "object") return false; + switch (ast.type) { + case "Literal": + return true; + + case "Identifier": + return true; + + case "UnaryExpression": + return (ast.operator === "-" || ast.operator === "+") && ast.argument.type === "Literal"; + + case "MemberExpression": + try { + switch (context.functionNode.getVariableSignature(ast)) { + case "this.thread.value": + case "this.output.value": + return true; + + case "this.constants.value": + return !context.mutatedNames.has(thisWrite); + + case "value.value": + return context.functionNode.isAstMathVariable(ast); + + default: + return false; + } + } catch (e) { + return false; + } + + default: + return false; + } + } + function cloneInlineNodes(context, nodes, bindings, renames) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneInlineNode(context, nodes[i], bindings, renames); + return result; + } + function cloneInlineNode(context, node, bindings, renames) { + if (!node || typeof node !== "object") return node; + if (Array.isArray(node)) return cloneInlineNodes(context, node, bindings, renames); + if (typeof node.type !== "string") return node; + if (node.type === "Identifier") { + const bound = bindings.get(node.name); + if (bound) return bound.atom ? cloneNode(context, bound.atom, null, 0) : stampSynthetic({ + type: "Identifier", + name: bound.name + }, node); + return stampSynthetic({ + type: "Identifier", + name: renames.get(node.name) || node.name + }, node); + } + const copy = {}; + const verbatimProperty = node.type === "MemberExpression" && !node.computed; + for (const key in node) { + if (key === "start" || key === "end") continue; + if (key === "loc" || key === "range" || key === "parent") { + copy[key] = node[key]; + continue; + } + copy[key] = verbatimProperty && key === "property" ? cloneNode(context, node[key], null, 0) : cloneInlineNode(context, node[key], bindings, renames); + } + return stampSynthetic(copy, node); + } + function reduceReturns(statements) { + let first = -1; + for (let i = 0; i < statements.length; i++) if (containsReturn(statements[i])) { + first = i; + break; + } + if (first === -1) return { + statements: statements, + value: null + }; + const value = tailExpression(statements, first); + if (value === null) return null; + return { + statements: statements.slice(0, first), + value: value + }; + } + function tailExpression(list, i) { + if (i >= list.length) return null; + const statement = list[i]; + if (statement.type === "ReturnStatement") { + if (i !== list.length - 1 || !statement.argument) return null; + return statement.argument; + } + if (statement.type !== "IfStatement") return null; + const consequent = branchExpression(statement.consequent); + if (consequent === null) return null; + let alternate; + if (statement.alternate) { + if (i !== list.length - 1) return null; + alternate = branchExpression(statement.alternate); + } else alternate = tailExpression(list, i + 1); + if (alternate === null) return null; + if (!isBranchSafe(consequent) || !isBranchSafe(alternate)) return null; + const consequentKind = branchLiteralKind(consequent); + const alternateKind = branchLiteralKind(alternate); + if (consequentKind !== "unknown" && alternateKind !== "unknown" && consequentKind !== alternateKind) return null; + return stampSynthetic({ + type: "ConditionalExpression", + test: statement.test, + consequent: consequent, + alternate: alternate + }, statement); + } + function branchLiteralKind(ast) { + if (!ast) return "unknown"; + if (ast.type === "Literal" && typeof ast.value === "number") return Number.isInteger(ast.value) ? "int" : "float"; + if (ast.type === "BinaryExpression" && "+-*/".indexOf(ast.operator) > -1) { + const left = branchLiteralKind(ast.left); + const right = branchLiteralKind(ast.right); + if (left === "float" || right === "float") return "float"; + if (left === "unknown" || right === "unknown") return "unknown"; + return ast.operator === "/" ? "unknown" : "int"; + } + return "unknown"; + } + function branchExpression(branch) { + if (!branch) return null; + return tailExpression(branch.type === "BlockStatement" ? branch.body : [ branch ], 0); + } + function containsReturn(ast) { + let found = false; + walk(ast, node => { + if (node.type === "ReturnStatement") found = true; + }); + return found; + } + function isBranchSafe(ast) { + let safe = true; + walk(ast, node => { + if (node.type === "CallExpression" && !isPureMathCall(node)) safe = false; + }); + return safe; + } + function buildInlinePlan(builder) { + const entries = new Map; + const kernel = builder.kernel || {}; + const allowedFree = new Set([ "Math", "Infinity" ]); + if (kernel.constants) for (const name in kernel.constants) allowedFree.add(name); + for (let i = 0; i < builder.nativeFunctionNames.length; i++) allowedFree.add(builder.nativeFunctionNames[i]); + for (const name in builder.functionMap) { + const node = builder.functionMap[name]; + if (!node) continue; + let ast = null; + try { + ast = node.getRawAST(); + } catch (e) { + ast = null; + } + if (!ast || !ast.body || ast.body.type !== "BlockStatement") continue; + const shadowed = builder.nativeFunctionNames.indexOf(name) > -1; + const declaredTypes = Boolean(node.hasDeclaredTypes); + const kind = node.isRootKernel ? "root" : node.isSubKernel || shadowed || declaredTypes ? "subKernel" : "helper"; + registerPlanEntry(entries, name, ast, kind, allowedFree); + } + for (const entry of entries.values()) allowedFree.add(entry.name); + for (const entry of entries.values()) analyzePlanEntry(entry, allowedFree); + let effectsChanged = true; + while (effectsChanged) { + effectsChanged = false; + for (const entry of entries.values()) { + if (entry.hasEffects) continue; + for (let i = 0; i < entry.calls.length; i++) { + const callee = entries.get(entry.calls[i]); + if (callee && callee.hasEffects) { + entry.hasEffects = true; + effectsChanged = true; + break; + } + } + } + } + markRecursive(entries); + let changed = true; + while (changed) { + changed = false; + for (const entry of entries.values()) entry.sites = []; + const blocked = new Set; + for (const entry of entries.values()) scanPlanEntry(entries, entry, blocked); + for (const name of blocked) { + const entry = entries.get(name); + if (entry && entry.inlinable) { + entry.inlinable = false; + changed = true; + } + } + if (!changed && applyInlineBudget(entries)) changed = true; + } + const plan = new Map; + for (const entry of entries.values()) { + if (!entry.inlinable) continue; + plan.set(entry.name, { + params: entry.params, + body: entry.body, + assignedParams: entry.assignedParams, + localNames: entry.localNames, + returnsValue: entry.returnsValue + }); + } + for (const entry of entries.values()) if (entry.inlinable && entry.sites.length > 1) { + entry.inlinable = false; + entry.sites = []; + } + return plan; + } + function registerPlanEntry(entries, name, ast, kind, allowedFree) { + if (!entries.has(name)) entries.set(name, { + name: name, + ast: ast, + kind: kind, + params: (ast.params || []).map(param => param.type === "Identifier" ? param.name : null), + body: ast.body.body, + assignedParams: new Set, + localNames: new Set, + returnsValue: false, + inlinable: kind === "helper", + recursive: false, + calls: [], + sites: [], + selfSize: 0, + expandedSize: 0 + }); + const nested = []; + walk(ast.body, node => { + if (node.type === "FunctionDeclaration" && node.id && node.id.name) nested.push(node); + }); + for (let i = 0; i < nested.length; i++) registerPlanEntry(entries, nested[i].id.name, nested[i], "helper", allowedFree); + } + function analyzePlanEntry(entry, allowedFree) { + entry.selfSize = nodeCount(entry.body); + const declared = new Set; + const assigned = new Set; + const free = new Set; + let rejected = false; + let hasEffects = false; + walk(entry.body, node => { + if (node.type === "CallExpression" && node.callee && node.callee.type === "MemberExpression" && node.callee.object && node.callee.object.name === "Math" && node.callee.property && node.callee.property.name === "random") hasEffects = true; + }); + const visit = node => { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "LabeledStatement": + rejected = true; + return; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + rejected = true; + return; + + case "VariableDeclarator": + if (node.id && node.id.type === "Identifier") declared.add(node.id.name); + break; + + case "AssignmentExpression": + if (node.left.type === "Identifier") assigned.add(node.left.name); + break; + + case "UpdateExpression": + if (node.argument.type === "Identifier") assigned.add(node.argument.name); + break; + + case "Identifier": + free.add(node.name); + break; + + case "MemberExpression": + visit(node.object); + if (node.computed) visit(node.property); + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child); + } + }; + visit(entry.body); + for (let i = 0; i < entry.params.length; i++) if (entry.params[i] === null) rejected = true; + if (rejected) { + entry.inlinable = false; + return; + } + for (const name of free) { + if (declared.has(name) || entry.params.indexOf(name) > -1 || allowedFree.has(name)) continue; + entry.inlinable = false; + return; + } + entry.localNames = declared; + for (let i = 0; i < entry.params.length; i++) if (assigned.has(entry.params[i])) entry.assignedParams.add(entry.params[i]); + for (const name of assigned) if (!declared.has(name) && entry.params.indexOf(name) === -1) hasEffects = true; + entry.hasEffects = hasEffects; + const reduced = reduceReturns(entry.body); + if (!reduced) { + entry.inlinable = false; + return; + } + entry.returnsValue = reduced.value !== null; + if (entry.selfSize > INLINE_MAX_HELPER_NODES) entry.inlinable = false; + } + function scanPlanEntry(entries, entry, blocked) { + const candidates = name => { + const target = entries.get(name); + return target && target.inlinable && !target.recursive ? target : null; + }; + const hoisted = new Set; + const scan = { + candidates: candidates, + sites: [], + clean: true + }; + const walkStatements = list => { + for (let i = 0; i < list.length; i++) walkStatement(list[i]); + }; + const walkStatement = statement => { + if (!statement || typeof statement.type !== "string") return; + if (statement.type === "FunctionDeclaration") return; + scan.clean = true; + scan.sites = []; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + for (let i = 0; i < scan.sites.length; i++) { + hoisted.add(scan.sites[i].node); + entry.sites.push(scan.sites[i]); + } + switch (statement.type) { + case "BlockStatement": + walkStatements(statement.body); + return; + + case "IfStatement": + walkStatement(statement.consequent); + if (statement.alternate) walkStatement(statement.alternate); + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + walkStatement(statement.body); + return; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) walkStatements(statement.cases[i].consequent); + return; } - return argumentTypes; - } - static getSignature(kernel, argumentTypes) { - throw new Error(`"getSignature" not implemented on ${this.name}`); + }; + walkStatements(entry.body); + walkOwn(entry.body, node => { + if (node.type !== "CallExpression" || hoisted.has(node)) return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) blocked.add(name); + }); + for (let i = 0; i < entry.sites.length; i++) { + const site = entry.sites[i]; + if (site.node.arguments.length < site.entry.params.length) blocked.add(site.entry.name); + for (let j = 0; j < site.node.arguments.length; j++) if (site.node.arguments[j].type === "SpreadElement") blocked.add(site.entry.name); } - functionToIGPUFunction(source, settings = {}) { - if (typeof source !== "string" && typeof source !== "function") throw new Error("source not a string or function"); - const sourceString = typeof source === "string" ? source : source.toString(); - let argumentTypes = []; - if (Array.isArray(settings.argumentTypes)) argumentTypes = settings.argumentTypes; else if (typeof settings.argumentTypes === "object") { - const argumentNames = utils.getArgumentNamesFromString(sourceString); - argumentTypes = argumentNames.map(name => settings.argumentTypes[name]) || []; - const keys = Object.keys(settings.argumentTypes); - if (keys.length > 0 && argumentNames.length > 0 && argumentTypes.every(type => type === void 0)) throw new Error(`argumentTypes keys [${keys.join(", ")}] match none of the function's parameters [${argumentNames.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${keys.map(k => settings.argumentTypes[k]).join("', '")}']`); - } else argumentTypes = settings.argumentTypes || []; - return { - name: settings.name || utils.getFunctionNameFromString(sourceString) || (typeof source === "function" && source.name ? source.name : null), - source: sourceString, - argumentTypes: argumentTypes, - returnType: settings.returnType || null - }; + } + function markRecursive(entries) { + const edges = new Map; + for (const entry of entries.values()) { + const out = new Set; + walkOwn(entry.body, node => { + if (node.type !== "CallExpression") return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) out.add(name); + }); + edges.set(entry.name, out); } - onActivate(previousKernel) {} - switchKernels(reason) { - if (this.switchingKernels) this.switchingKernels.push(reason); else this.switchingKernels = [ reason ]; + const state = new Map; + const onStack = []; + const visit = name => { + if (state.get(name) === "done") return; + if (state.get(name) === "open") { + for (let i = onStack.lastIndexOf(name); i < onStack.length; i++) { + entries.get(onStack[i]).recursive = true; + entries.get(onStack[i]).inlinable = false; + } + return; + } + state.set(name, "open"); + onStack.push(name); + for (const next of edges.get(name) || []) visit(next); + onStack.pop(); + state.set(name, "done"); + }; + for (const name of entries.keys()) visit(name); + } + function applyInlineBudget(entries) { + let bounded = false; + let shed = false; + while (!bounded) { + computeExpandedSizes(entries); + for (const entry of entries.values()) if (entry.inlinable && entry.expandedSize > INLINE_MAX_HELPER_NODES) { + entry.inlinable = false; + shed = true; + } + bounded = true; + let worst = null; + let worstAdded = INLINE_MAX_ADDED_NODES; + for (const entry of entries.values()) { + let added = 0; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) added += callee.expandedSize; + } + if (added > worstAdded) { + worstAdded = added; + worst = entry; + } + } + if (!worst) break; + let victim = null; + for (let i = 0; i < worst.sites.length; i++) { + const callee = entries.get(worst.sites[i].entry.name); + if (!callee || !callee.inlinable) continue; + if (!victim || callee.expandedSize > victim.expandedSize || callee.expandedSize === victim.expandedSize && callee.name < victim.name) victim = callee; + } + if (!victim) break; + victim.inlinable = false; + shed = true; + bounded = false; + } + return shed; + } + function computeExpandedSizes(entries) { + const pending = new Set(entries.keys()); + for (const entry of entries.values()) entry.expandedSize = entry.selfSize; + for (let round = 0; round < pending.size + 1; round++) { + let changed = false; + for (const entry of entries.values()) { + let size = entry.selfSize; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) size += callee.expandedSize; + } + if (size !== entry.expandedSize) { + entry.expandedSize = size; + changed = true; + } + } + if (!changed) break; } - resetSwitchingKernels() { - const existingValue = this.switchingKernels; - this.switchingKernels = null; - return existingValue; + } + function nodeCount(ast) { + let count = 0; + walk(ast, () => { + count++; + }); + return count; + } + function unrollBlock(context, block) { + block.body = unrollList(context, block.body); + } + function unrollList(context, list) { + const result = []; + for (let i = 0; i < list.length; i++) { + const replacement = unrollStatement(context, list[i]); + if (replacement === null) { + result.push(list[i]); + continue; + } + for (let j = 0; j < replacement.length; j++) result.push(replacement[j]); } - checkArgumentTypes(args) { - if (!this.argumentTypes) return; - const length = Math.min(args.length, this.argumentTypes.length); - for (let i = 0; i < length; i++) if (!utils.typeFitsValue(this.argumentTypes[i], args[i])) this.switchKernels({ - type: "argumentTypeMismatch", - index: i, - needed: utils.getVariableType(args[i], this.strictIntegers) - }); + return result; + } + function unrollStatement(context, statement) { + switch (statement.type) { + case "BlockStatement": + unrollBlock(context, statement); + return null; + + case "IfStatement": + statement.consequent = unrollBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = unrollBranch(context, statement.alternate); + return null; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) statement.cases[i].consequent = unrollList(context, statement.cases[i].consequent); + return null; + + case "WhileStatement": + case "DoWhileStatement": + statement.body = unrollBranch(context, statement.body); + return null; + + case "ForStatement": + statement.body = unrollBranch(context, statement.body); + return unrollLoop(context, statement); + + default: + return null; } + } + function unrollBranch(context, branch) { + if (!branch) return branch; + if (branch.type === "BlockStatement") { + unrollBlock(context, branch); + return branch; + } + const replacement = unrollStatement(context, branch); + if (replacement === null) return branch; + return stampSynthetic({ + type: "BlockStatement", + body: replacement + }, branch); + } + function unrollLoop(context, loop) { + if (!(context.loopUnrollLimit > 0)) return null; + if (loop.type !== "ForStatement") return null; + const induction = inductionVariable(context, loop); + if (!induction) return null; + const values = tripValues(loop, induction, context.loopUnrollLimit); + if (!values) return null; + if (loop.init && loop.init.type === "VariableDeclaration" && loop.init.declarations[0].init.type !== "Literal") { + const cap = context.functionNode.loopMaxIterations || 1e3; + if (values.length > cap) return null; + } + const body = loop.body ? loop.body.type === "BlockStatement" ? loop.body.body : [ loop.body ] : []; + if (!bodyIsUnrollable(body, induction.name)) return null; + const added = countNodes(body) * (values.length - 1); + if (context.unrollAdded === void 0) context.unrollAdded = 0; + if (context.unrollAdded + added > UNROLL_MAX_ADDED_NODES) return null; + context.unrollAdded += added; + const result = []; + for (let i = 0; i < values.length; i++) result.push(stampSynthetic({ + type: "BlockStatement", + body: cloneNodes(context, body, induction.name, values[i]) + }, loop)); + return result; + } + function countNodes(ast) { + let count = 0; + walk(ast, () => { + count++; + }); + return count; + } + function inductionVariable(context, loop) { + const {init: init} = loop; + if (!init || init.type !== "VariableDeclaration") return null; + if (init.declarations.length !== 1) return null; + const declaration = init.declarations[0]; + if (!declaration.id || declaration.id.type !== "Identifier") return null; + const start = integerLiteral(declaration.init); + if (start === null) return null; + if (init.kind === "var" && nameUsedOutside(context, loop, declaration.id.name)) return null; + return { + name: declaration.id.name, + start: start + }; + } + const comparators = { + "<": (value, bound) => value < bound, + "<=": (value, bound) => value <= bound, + ">": (value, bound) => value > bound, + ">=": (value, bound) => value >= bound, + "!==": (value, bound) => value !== bound, + "!=": (value, bound) => value !== bound }; - function splitArgumentTypes(argumentTypesObject) { - const argumentNames = Object.keys(argumentTypesObject); - const argumentTypes = []; - for (let i = 0; i < argumentNames.length; i++) { - const argumentName = argumentNames[i]; - argumentTypes.push(argumentTypesObject[argumentName]); + function tripValues(loop, induction, limit) { + const {test: test, update: update} = loop; + if (!test || test.type !== "BinaryExpression") return null; + if (!test.left || test.left.type !== "Identifier" || test.left.name !== induction.name) return null; + const bound = integerLiteral(test.right); + if (bound === null) return null; + const compare = comparators[test.operator]; + if (!compare) return null; + const step = inductionStep(update, induction.name); + if (step === null) return null; + const values = []; + let value = induction.start; + while (compare(value, bound)) { + if (values.length >= limit) return null; + values.push(value); + value += step; + } + return values; + } + function inductionStep(update, name) { + if (!update) return null; + if (update.type === "UpdateExpression") { + if (!update.argument || update.argument.type !== "Identifier" || update.argument.name !== name) return null; + return update.operator === "++" ? 1 : update.operator === "--" ? -1 : null; + } + if (update.type !== "AssignmentExpression") return null; + if (!update.left || update.left.type !== "Identifier" || update.left.name !== name) return null; + switch (update.operator) { + case "+=": + { + const step = integerLiteral(update.right); + return step === 0 ? null : step; + } + + case "-=": + { + const step = integerLiteral(update.right); + return step === null || step === 0 ? null : -step; + } + + case "=": + { + const {right: right} = update; + if (!right || right.type !== "BinaryExpression") return null; + const leftIsCounter = right.left.type === "Identifier" && right.left.name === name; + const rightIsCounter = right.right.type === "Identifier" && right.right.name === name; + if (right.operator === "+") { + const step = leftIsCounter ? integerLiteral(right.right) : rightIsCounter ? integerLiteral(right.left) : null; + return step === 0 ? null : step; + } + if (right.operator === "-" && leftIsCounter) { + const step = integerLiteral(right.right); + return step === null || step === 0 ? null : -step; + } + return null; + } + + default: + return null; } - return { - argumentTypes: argumentTypes, - argumentNames: argumentNames + } + function integerLiteral(ast) { + const value = literalNumber(ast); + return value === null || !Number.isInteger(value) ? null : value; + } + function nameUsedOutside(context, loop, name) { + let found = false; + const visit = node => { + if (found || !node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== "string" || node === loop) return; + if (node.type === "Identifier" && node.name === name) { + found = true; + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child); + } + }; + visit(context.ast); + return found; + } + function bodyIsUnrollable(body, name) { + let ok = true; + const reject = () => { + ok = false; + }; + const visit = (node, inBreakable, inContinuable) => { + if (!ok || !node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "AssignmentExpression": + if (node.left.type === "Identifier" && node.left.name === name) return reject(); + break; + + case "UpdateExpression": + if (node.argument.type === "Identifier" && node.argument.name === name) return reject(); + break; + + case "VariableDeclarator": + if (node.id.type === "Identifier" && node.id.name === name) return reject(); + break; + + case "BreakStatement": + if (node.label || !inBreakable) return reject(); + return; + + case "ContinueStatement": + if (node.label || !inContinuable) return reject(); + return; + + case "LabeledStatement": + return reject(); + + case "CallExpression": + if (isMathRandom(node)) return reject(); + break; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return reject(); + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + + case "SwitchStatement": + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + + case "MemberExpression": + visit(node.object, inBreakable, inContinuable); + if (node.computed) visit(node.property, inBreakable, inContinuable); + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child, inBreakable, inContinuable); + } }; + visit(body, false, false); + return ok; + } + function numberNode(value, source) { + const literal = stampSynthetic({ + type: "Literal", + value: Math.abs(value), + raw: `${Math.abs(value)}` + }, source); + if (value >= 0) return literal; + return stampSynthetic({ + type: "UnaryExpression", + operator: "-", + prefix: true, + argument: literal + }, source); + } + function isMathRandom(ast) { + const {callee: callee} = ast; + return Boolean(callee) && callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "Math" && callee.property.name === "random"; + } + function cloneNodes(context, nodes, name, value) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneNode(context, nodes[i], name, value); + return result; + } + function cloneNode(context, node, name, value) { + if (!node || typeof node !== "object") return node; + if (Array.isArray(node)) return cloneNodes(context, node, name, value); + if (typeof node.type !== "string") return node; + if (name !== null && node.type === "Identifier" && node.name === name) return numberNode(value, node); + const copy = {}; + const verbatimProperty = node.type === "MemberExpression" && !node.computed; + for (const key in node) { + if (key === "start" || key === "end") continue; + if (key === "loc" || key === "range" || key === "parent") { + copy[key] = node[key]; + continue; + } + copy[key] = cloneNode(context, node[key], verbatimProperty && key === "property" ? null : name, value); + } + return stampSynthetic(copy, node); + } + function threadLocalName(functionNode, name) { + if (!functionNode.localizeThreadCoordinates) return null; + if (functionNode.optimizerDisabled || !functionNode.isRootKernel) return null; + const {output: output} = functionNode; + if (!output || !output.length) return null; + switch (name) { + case "x": + return "x"; + + case "y": + return output.length > 1 ? "y" : "0"; + + case "z": + return output.length > 2 ? "z" : "0"; + + default: + return null; + } } module.exports = { - Kernel: Kernel + optimize: optimize, + buildInlinePlan: buildInlinePlan, + threadLocalName: threadLocalName }; }); var require_function_builder = __commonJSMin((exports, module) => { + const {buildInlinePlan: buildInlinePlan} = require_optimizer(); module.exports = { FunctionBuilder: class FunctionBuilder { static fromKernel(kernel, FunctionNode, extraNodeOptions) { - const {kernelArguments: kernelArguments, kernelConstants: kernelConstants, argumentNames: argumentNames, argumentSizes: argumentSizes, argumentBitRatios: argumentBitRatios, constants: constants, constantBitRatios: constantBitRatios, debug: debug, loopMaxIterations: loopMaxIterations, nativeFunctions: nativeFunctions, output: output, optimizeFloatMemory: optimizeFloatMemory, precision: precision, plugins: plugins, source: source, subKernels: subKernels, functions: functions, leadingReturnStatement: leadingReturnStatement, followingReturnStatement: followingReturnStatement, dynamicArguments: dynamicArguments, dynamicOutput: dynamicOutput} = kernel; + const {kernelArguments: kernelArguments, kernelConstants: kernelConstants, argumentNames: argumentNames, argumentSizes: argumentSizes, argumentBitRatios: argumentBitRatios, constants: constants, constantBitRatios: constantBitRatios, debug: debug, loopMaxIterations: loopMaxIterations, nativeFunctions: nativeFunctions, output: output, optimizeFloatMemory: optimizeFloatMemory, precision: precision, plugins: plugins, source: source, subKernels: subKernels, functions: functions, leadingReturnStatement: leadingReturnStatement, followingReturnStatement: followingReturnStatement, dynamicArguments: dynamicArguments, dynamicOutput: dynamicOutput, loopUnrollLimit: loopUnrollLimit, localizeThreadCoordinates: localizeThreadCoordinates} = kernel; + const optimizerDisabled = Boolean(kernel._optimizerDisabled); + const inliningDisabled = Boolean(kernel._inliningDisabled); const argumentTypes = new Array(kernelArguments.length); const constantTypes = {}; for (let i = 0; i < kernelArguments.length; i++) argumentTypes[i] = kernelArguments[i].type; @@ -1548,6 +3244,7 @@ const onFunctionCall = (functionName, calleeFunctionName, args) => { functionBuilder.trackFunctionCall(functionName, calleeFunctionName, args); }; + const lookupInlineTarget = inliningDisabled ? null : functionName => functionBuilder.lookupInlineTarget(functionName); const onNestedFunction = (ast, source) => { const argumentNames = []; for (let i = 0; i < ast.params.length; i++) argumentNames.push(ast.params[i].name); @@ -1591,7 +3288,11 @@ output: output, plugins: plugins, dynamicArguments: dynamicArguments, - dynamicOutput: dynamicOutput + dynamicOutput: dynamicOutput, + optimizerDisabled: optimizerDisabled, + loopUnrollLimit: loopUnrollLimit, + localizeThreadCoordinates: localizeThreadCoordinates, + lookupInlineTarget: lookupInlineTarget }, extraNodeOptions || {}); const rootNodeOptions = Object.assign({}, nodeOptions, { isRootKernel: true, @@ -1610,6 +3311,7 @@ name: fn.name || void 0, returnType: fn.returnType, argumentTypes: fn.argumentTypes, + hasDeclaredTypes: Boolean(fn.returnType) || (Array.isArray(fn.argumentTypes) ? fn.argumentTypes.some(type => Boolean(type)) : Boolean(fn.argumentTypes && Object.keys(fn.argumentTypes).length > 0)), output: output, plugins: plugins, constants: constants, @@ -1626,7 +3328,11 @@ triggerImplyArgumentType: triggerImplyArgumentType, triggerImplyArgumentBitRatio: triggerImplyArgumentBitRatio, onFunctionCall: onFunctionCall, - onNestedFunction: onNestedFunction + onNestedFunction: onNestedFunction, + optimizerDisabled: optimizerDisabled, + loopUnrollLimit: loopUnrollLimit, + localizeThreadCoordinates: localizeThreadCoordinates, + lookupInlineTarget: lookupInlineTarget })); let subKernelNodes = null; if (subKernels) subKernelNodes = subKernels.map(subKernel => { @@ -1658,6 +3364,7 @@ this.lookupChain = []; this.functionNodeDependencies = {}; this.functionCalls = {}; + this._inlinePlan = null; if (this.rootNode) this.functionMap["kernel"] = this.rootNode; if (this.functionNodes) for (let i = 0; i < this.functionNodes.length; i++) this.functionMap[this.functionNodes[i].name] = this.functionNodes[i]; if (this.subKernelNodes) for (let i = 0; i < this.subKernelNodes.length; i++) this.functionMap[this.subKernelNodes[i].name] = this.subKernelNodes[i]; @@ -1666,6 +3373,10 @@ this.nativeFunctionNames.push(nativeFunction.name); } } + lookupInlineTarget(functionName) { + if (!this._inlinePlan) this._inlinePlan = buildInlinePlan(this); + return this._inlinePlan.get(functionName) || null; + } addFunctionNode(functionNode) { if (!functionNode.name) throw new Error("functionNode.name needs set"); this.functionMap[functionNode.name] = functionNode; @@ -2158,6 +3869,7 @@ const acorn = require_empty_module(); const {utils: utils} = require_utils(); const {FunctionTracer: FunctionTracer} = require_function_tracer(); + const {optimize: optimize} = require_optimizer(); const mathProperties = [ "E", "PI", "SQRT2", "SQRT1_2", "LN2", "LN10", "LOG2E", "LOG10E" ]; const mathFunctions = [ "abs", "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cbrt", "ceil", "clz32", "cos", "cosh", "expm1", "exp", "floor", "fround", "imul", "log", "log2", "log10", "log1p", "max", "min", "pow", "random", "round", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "trunc" ]; const allowedExpressions = [ "value", "value[]", "value[][]", "value[][][]", "value[][][][]", "value.value", "value.thread.value", "this.thread.value", "this.output.value", "this.constants.value", "this.constants.value[]", "this.constants.value[][]", "this.constants.value[][][]", "this.constants.value[][][][]", "fn()[]", "fn()[][]", "fn()[][][]", "[][]" ]; @@ -2205,6 +3917,11 @@ this.dynamicArguments = null; this.strictTypingChecking = false; this.fixIntegerDivisionAccuracy = null; + this.optimizerDisabled = false; + this.loopUnrollLimit = 8; + this.lookupInlineTarget = null; + this.hasDeclaredTypes = false; + this.localizeThreadCoordinates = false; if (settings) for (const p in settings) { if (!settings.hasOwnProperty(p)) continue; if (!this.hasOwnProperty(p)) continue; @@ -2212,6 +3929,7 @@ } this.literalTypes = {}; this.validate(); + this._rawAST = null; this._string = null; this._internalVariableNames = {}; } @@ -2259,25 +3977,46 @@ get requiresSequenceFreeForInit() { return false; } - getJsAST(inParser) { - if (this.ast) return this.ast; + get readsCanFault() { + return false; + } + get readsFaultAtOneLevel() { + return false; + } + getRawAST(inParser) { + if (this._rawAST) return this._rawAST; if (typeof this.source === "object") { normalizeMinifiedStatements(this.source, this.requiresSequenceFreeForInit); - this.traceFunctionAST(this.source); - return this.ast = this.source; + return this._rawAST = this.source; } inParser = inParser || acorn; if (inParser === null) throw new Error("Missing JS to AST parser"); - const ast = Object.freeze(inParser.parse(`const parser_${this.name} = ${this.source};`, { + const functionAST = Object.freeze(inParser.parse(`const parser_${this.name} = ${this.source};`, { locations: true, ecmaVersion: 2020 - })); - const functionAST = ast.body[0].declarations[0].init; + })).body[0].declarations[0].init; normalizeMinifiedStatements(functionAST, this.requiresSequenceFreeForInit); + return this._rawAST = functionAST; + } + getJsAST(inParser) { + if (this.ast) return this.ast; + const functionAST = this.getRawAST(inParser); + try { + this.optimizeAST(functionAST); + } catch (e) { + if (e && typeof e === "object") e.isOptimizerFailure = true; + throw e; + } this.traceFunctionAST(functionAST); - if (!ast) throw new Error("Failed to parse JS code"); return this.ast = functionAST; } + optimizeAST(ast) { + if (this.optimizerDisabled) return ast; + return optimize(this, ast, { + loopUnrollLimit: this.loopUnrollLimit, + lookupInlineTarget: this.lookupInlineTarget + }); + } getAssignedArguments() { if (this._assignedArguments) return this._assignedArguments; const assigned = new Set; @@ -2977,8 +4716,11 @@ astUnaryExpression(uNode, retArr) { if (this.checkAndUpconvertBitwiseUnary(uNode, retArr)) return retArr; if (uNode.prefix) { + const collides = uNode.operator === "-" || uNode.operator === "+"; + if (collides) retArr.push("("); retArr.push(uNode.operator); this.astGeneric(uNode.argument, retArr); + if (collides) retArr.push(")"); } else { this.astGeneric(uNode.argument, retArr); retArr.push(uNode.operator); @@ -3469,7 +5211,11 @@ }); var require_function_node$4 = __commonJSMin((exports, module) => { const {FunctionNode: FunctionNode} = require_function_node$5(); + const {threadLocalName: threadLocalName} = require_optimizer(); var CPUFunctionNode = class extends FunctionNode { + get readsCanFault() { + return true; + } markupUserName(name) { if (this.isRootKernel && this.getAssignedArguments().has(name)) return `cellShadow_user_${name}`; return `user_${name}`; @@ -3692,8 +5438,11 @@ const {signature: signature, type: type, property: property, xProperty: xProperty, yProperty: yProperty, zProperty: zProperty, name: name, origin: origin} = this.getMemberExpressionDetails(mNode); switch (signature) { case "this.thread.value": - retArr.push(`_this.thread.${name}`); - return retArr; + { + const local = threadLocalName(this, name); + retArr.push(local === null ? `_this.thread.${name}` : local); + return retArr; + } case "this.output.value": switch (name) { @@ -4044,6 +5793,7 @@ } constructor(source, settings) { super(source, settings); + this._inliningDisabled = true; this.mergeSettings(source.settings || settings); this._imageData = null; this._colorData = null; @@ -4099,7 +5849,7 @@ this.setupConstants(); this.setupArguments(arguments); this.validateSettings(arguments); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); if (this.graphical) { const {canvas: canvas, output: output} = this; if (!canvas) throw new Error("no canvas available for using graphical output"); @@ -5780,7 +7530,7 @@ astBinaryExpression(ast, retArr) { if (this.checkAndUpconvertOperator(ast, retArr)) return retArr; if (ast.operator === "/") { - const wrap = this.fixIntegerDivisionAccuracy; + const wrap = this.fixIntegerDivisionAccuracy && !this.divisionIsProvablyFractional(ast); retArr.push(wrap ? "divWithIntCheck(" : "("); this.pushState("building-float"); switch (this.getType(ast.left)) { @@ -5953,6 +7703,9 @@ retArr.push(")"); return retArr; } + divisionIsProvablyFractional(ast) { + return isFractionalLiteral(ast.left) || isFractionalLiteral(ast.right); + } checkAndUpconvertOperator(ast, retArr) { const bitwiseResult = this.checkAndUpconvertBitwiseOperators(ast, retArr); if (bitwiseResult) return bitwiseResult; @@ -6911,7 +8664,8 @@ astSwitchStatement(ast, retArr) { if (ast.type !== "SwitchStatement") throw this.astErrorOutput("Invalid switch statement", ast); const {discriminant: discriminant, cases: cases} = ast; - const type = this.getType(discriminant); + const literalDiscriminant = this.getType(discriminant) === "LiteralInteger"; + const type = literalDiscriminant ? "Integer" : this.getType(discriminant); const varName = `switchDiscriminant${this.astKey(ast, "_")}`; switch (type) { case "Float": @@ -6923,7 +8677,7 @@ case "Integer": retArr.push(`int ${varName} = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) this.castLiteralToInteger(discriminant, retArr); else this.astGeneric(discriminant, retArr); retArr.push(";\n"); break; } @@ -7332,7 +9086,9 @@ retArr.push(")"); continue; } else if (targetType === "Integer") { + this.pushState("building-integer"); this.astGeneric(argument, retArr); + this.popState("building-integer"); continue; } break; @@ -7428,6 +9184,12 @@ this.castLiteralToInteger(property, result); break; + case "Integer": + this.pushState("building-integer"); + this.astGeneric(property, result); + this.popState("building-integer"); + break; + default: this.astGeneric(property, result); } @@ -7569,6 +9331,11 @@ "===": "==", "!==": "!=" }; + function isFractionalLiteral(ast) { + if (!ast) return false; + if (ast.type === "UnaryExpression" && (ast.operator === "-" || ast.operator === "+")) return isFractionalLiteral(ast.argument); + return ast.type === "Literal" && typeof ast.value === "number" && !Number.isInteger(ast.value); + } module.exports = { WebGLFunctionNode: WebGLFunctionNode }; @@ -9417,13 +11184,23 @@ }; return this.canvas.getContext("webgl", settings) || this.canvas.getContext("experimental-webgl", settings); } + pluginMatchSource() { + if (typeof this.source !== "string") return null; + if (!this.functions || this.functions.length < 1) return this.source; + const sources = [ this.source ]; + for (let i = 0; i < this.functions.length; i++) { + const source = this.functions[i] ? this.functions[i].source : null; + if (typeof source === "string") sources.push(source); + } + return sources.join("\n"); + } initPlugins(settings) { const pluginsToUse = []; - const {source: source} = this; + const source = this.pluginMatchSource(); if (typeof source === "string") for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; if (source.match(plugin.functionMatch)) pluginsToUse.push(plugin); - } else if (typeof source === "object") { + } else if (typeof this.source === "object") { if (settings.pluginNames) for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; if (settings.pluginNames.some(pluginName => pluginName === plugin.name)) pluginsToUse.push(plugin); @@ -9608,7 +11385,7 @@ this.setupArguments(arguments); if (this.fallbackRequested) return; this.updateMaxTexSize(); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); const failureResult = this.pickRenderStrategy(arguments); if (failureResult) return failureResult; const {texSize: texSize, context: gl, canvas: canvas} = this; @@ -9951,7 +11728,9 @@ } _getPluginsString() { if (!this.plugins) return "\n"; - return this.plugins.map(plugin => plugin.source && this.source.match(plugin.functionMatch) ? plugin.source : "").join("\n"); + const source = this.pluginMatchSource(); + if (typeof source !== "string") return "\n"; + return this.plugins.map(plugin => plugin.source && source.match(plugin.functionMatch) ? plugin.source : "").join("\n"); } _getConstantsString() { const result = []; @@ -12275,7 +14054,8 @@ astSwitchStatement(ast, retArr) { if (ast.type !== "SwitchStatement") throw this.astErrorOutput("Invalid switch statement", ast); const {discriminant: discriminant, cases: cases} = ast; - const type = this.getType(discriminant); + const literalDiscriminant = this.getType(discriminant) === "LiteralInteger"; + const type = literalDiscriminant ? "Integer" : this.getType(discriminant); const varName = `switchDiscriminant${this.astKey(ast, "_")}`; switch (type) { case "Float": @@ -12287,7 +14067,7 @@ case "Integer": retArr.push(`var ${varName} : i32 = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) this.castLiteralToInteger(discriminant, retArr); else this.astGeneric(discriminant, retArr); retArr.push(";\n"); break; @@ -12605,7 +14385,9 @@ retArr.push(")"); continue; } else if (targetType === "Integer") { + this.pushState("building-integer"); this.astGeneric(argument, retArr); + this.popState("building-integer"); continue; } break; @@ -12991,9 +14773,11 @@ this.validateSettings(arguments); const threadDim = this.threadDim = Array.from(this.output); while (threadDim.length < 3) threadDim.push(1); - this.translateSource(); - this.paramsLayout = this.computeParamsLayout(); - this.compiledSource = this.assembleWGSL(); + this.buildWithOptimizer(() => { + this.translateSource(); + this.paramsLayout = this.computeParamsLayout(); + this.compiledSource = this.assembleWGSL(); + }); if (this.debug) { console.log("WGSL Shader Output:"); console.log(this.compiledSource); @@ -14437,6 +16221,12 @@ } } var WebAssemblyFunctionNode = class extends FunctionNode { + get readsCanFault() { + return true; + } + get readsFaultAtOneLevel() { + return true; + } constructor(source, settings) { super(source, settings); this.assembler = null; @@ -15172,6 +16962,13 @@ this.em.localSet(dLocal); break; + case "LiteralInteger": + dIsInt = true; + dLocal = this.em.addLocal("i32"); + this.castLiteralToInteger(discriminant); + this.em.localSet(dLocal); + break; + default: throw this.astErrorOutput(`Unhandled switch discriminant type "${type}"`, ast); } @@ -17233,6 +19030,13 @@ em.localSet(dLocal); break; + case "LiteralInteger": + dIsInt = true; + dLocal = em.addLocal("i32"); + this.castLiteralToInteger(discriminant); + em.localSet(dLocal); + break; + default: throw this.astErrorOutput(`Unhandled switch discriminant type "${type}"`, ast); } @@ -17276,6 +19080,7 @@ break; case "Integer": + case "LiteralInteger": dIsInt = true; dLocal = em.addLocal("v128"); this.vCoerce(this.vexpr(discriminant), "vi32"); @@ -18541,9 +20346,17 @@ this.validateSettings(arguments); const threadDim = this.threadDim = Array.from(this.output); while (threadDim.length < 3) threadDim.push(1); - if (!this.translateSource()) return this.requestFallback(arguments, `return type ${this.returnType} is not supported on the webasm backend`); - this.buildSignature(arguments); - this._instantiate(this._entryKey(arguments), arguments); + let unsupportedReturnType = false; + this.buildWithOptimizer(() => { + if (!this.translateSource()) { + unsupportedReturnType = true; + return; + } + unsupportedReturnType = false; + this.buildSignature(arguments); + this._instantiate(this._entryKey(arguments), arguments); + }); + if (unsupportedReturnType) return this.requestFallback(arguments, `return type ${this.returnType} is not supported on the webasm backend`); this.built = true; } validateSettings(args) { @@ -20543,7 +22356,7 @@ immutable: true, dynamicArguments: true }, overrides || {}); - const optional = [ "constants", "constantTypes", "precision", "loopMaxIterations", "strictIntegers", "fixIntegerDivisionAccuracy", "optimizeFloatMemory", "tactic", "functions", "nativeFunctions", "injectedNative", "debug", "randomSeed", "returnType" ]; + const optional = [ "constants", "constantTypes", "precision", "loopMaxIterations", "strictIntegers", "fixIntegerDivisionAccuracy", "optimizeFloatMemory", "tactic", "functions", "nativeFunctions", "injectedNative", "debug", "randomSeed", "returnType", "loopUnrollLimit", "_optimizerDisabled", "_inliningDisabled" ]; if (kernel.declaredArgumentTypes) settings.argumentTypes = kernel.declaredArgumentTypes.slice(); for (let i = 0; i < optional.length; i++) { const name = optional[i]; @@ -21000,6 +22813,8 @@ injectedNative: kernelRun.injectedNative, subKernels: kernelRun.subKernels, strictIntegers: kernelRun.strictIntegers, + _optimizerDisabled: kernelRun._optimizerDisabled, + loopUnrollLimit: kernelRun.loopUnrollLimit, randomSeed: kernelRun.randomSeed, debug: kernelRun.debug, asyncMode: kernelRun.asyncMode, @@ -21052,6 +22867,8 @@ injectedNative: _kernel.injectedNative, subKernels: _kernel.subKernels, strictIntegers: _kernel.strictIntegers, + _optimizerDisabled: _kernel._optimizerDisabled, + loopUnrollLimit: _kernel.loopUnrollLimit, randomSeed: _kernel.randomSeed, debug: _kernel.debug, asyncMode: _kernel.asyncMode, @@ -21129,6 +22946,8 @@ precision: currentKernel.precision, tactic: currentKernel.tactic, strictIntegers: currentKernel.strictIntegers, + _optimizerDisabled: currentKernel._optimizerDisabled, + loopUnrollLimit: currentKernel.loopUnrollLimit, fixIntegerDivisionAccuracy: currentKernel.fixIntegerDivisionAccuracy, subKernels: currentKernel.subKernels, graphical: currentKernel.graphical, diff --git a/dist/gpu-browser-core.min.js b/dist/gpu-browser-core.min.js index f89dd2fc..683179a6 100644 --- a/dist/gpu-browser-core.min.js +++ b/dist/gpu-browser-core.min.js @@ -5,11 +5,11 @@ * GPU Accelerated JavaScript * * @version 2.23.0 - * @date Mon Aug 03 2026 18:12:02 GMT+0800 (Singapore Standard Time) + * @date Wed Aug 05 2026 10:06:18 GMT+0800 (Singapore Standard Time) * * @license MIT * The MIT License * * Copyright (c) 2026 gpu.js Team */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):(e="undefined"!=typeof globalThis?globalThis:e||self).GPU=t()}(this,function(){var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),t=e((e,t)=>{function r(e){const t=new Array(e.length);for(let r=0;r{e.output=l(t),e.graphical&&u(e)},e.toJSON=()=>{throw new Error("Not usable with gpuMock")},e.setConstants=t=>(e.constants=t,e),e.setGraphical=t=>(e.graphical=t,e),e.setCanvas=t=>(e.canvas=t,e),e.setContext=t=>(e.context=t,e),e.destroy=()=>{},e.validateSettings=()=>{},e.graphical&&e.output&&u(e),e.exec=function(){return new Promise((t,r)=>{try{t(e.apply(e,arguments))}catch(e){r(e)}})},e.getPixels=t=>{const{x:r,y:n}=e.output;return t?function(e,t,r){const n=r/2|0,s=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee,r=["setWarnVarUsage","setArgumentTypes","setTactic","setOptimizeFloatMemory","setDebug","setLoopMaxIterations","setConstantTypes","setFunctions","setNativeFunctions","setInjectedNative","setPipeline","setPrecision","setOutputToTexture","setImmutable","setStrictIntegers","setDynamicOutput","setHardcodeConstants","setDynamicArguments","setUseLegacyEncoder","setWarnVarUsage","addSubKernel"];for(let n=0;n{t.exports={}}),n=e((e,t)=>{var r=class{constructor(e,t){this.value=e,Array.isArray(t)?this.size=t:(this.size=new Int32Array(3),t.z?this.size=new Int32Array([t.x,t.y,t.z]):t.y?this.size=new Int32Array([t.x,t.y]):this.size=new Int32Array([t.x]));const[r,n,s]=this.size;if(s){if(this.value.length!==r*n*s)throw new Error(`Input size ${this.value.length} does not match ${r} * ${n} * ${s} = ${n*r*s}`)}else if(n){if(this.value.length!==r*n)throw new Error(`Input size ${this.value.length} does not match ${r} * ${n} = ${n*r}`)}else if(this.value.length!==r)throw new Error(`Input size ${this.value.length} does not match ${r}`)}toArray(){const{utils:e}=i(),[t,r,n]=this.size;return n?e.erectMemoryOptimized3DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,r,n):r?e.erectMemoryOptimized2DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,r):this.value}};t.exports={Input:r,input:function(e,t){return new r(e,t)}}}),s=e((e,t)=>{t.exports={Texture:class{constructor(e){const{texture:t,size:r,dimensions:n,output:s,context:i,type:a="NumberTexture",kernel:o,internalFormat:u,textureFormat:l}=e;if(!s)throw new Error('settings property "output" required.');if(!i)throw new Error('settings property "context" required.');if(!t)throw new Error('settings property "texture" required.');if(!o)throw new Error('settings property "kernel" required.');this.texture=t,t._refs?t._refs++:t._refs=1,this.size=r,this.dimensions=n,this.output=s,this.context=i,this.kernel=o,this.type=a,this._deleted=!1,this.internalFormat=u,this.textureFormat=l}toArray(){throw new Error(`Not implemented on ${this.constructor.name}`)}clone(){throw new Error(`Not implemented on ${this.constructor.name}`)}delete(){throw new Error(`Not implemented on ${this.constructor.name}`)}clear(){throw new Error(`Not implemented on ${this.constructor.name}`)}}}}),i=e((e,t)=>{const i=r(),{Input:a}=n(),{Texture:o}=s(),u=/function ([^(]*)/,l=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,h=/([^\s,]+)/g,c={systemEndianness:()=>m,getSystemEndianness(){const e=new ArrayBuffer(4),t=new Uint32Array(e),r=new Uint8Array(e);if(t[0]=3735928559,239===r[0])return"LE";if(222===r[0])return"BE";throw new Error("unknown endianness")},isFunction:e=>"function"==typeof e,isFunctionString:e=>"string"==typeof e&&"function"===e.slice(0,8).toLowerCase(),getFunctionNameFromString(e){const t=u.exec(e);return t&&0!==t.length?t[1].trim():null},getFunctionBodyFromString:e=>e.substring(e.indexOf("{")+1,e.lastIndexOf("}")),getArgumentNamesFromString(e){const t=e.replace(l,"");let r=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(h);return null===r&&(r=[]),r},clone(e){if(null===e||"object"!=typeof e||e.hasOwnProperty("isActiveClone"))return e;const t=e.constructor();for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(e.isActiveClone=null,t[r]=c.clone(e[r]),delete e.isActiveClone);return t},isArray:e=>!isNaN(e.length),typeFitsValue(e,t){if("string"!=typeof e||null==t)return!0;if(t.type)return!0;switch(e){case"Input":return t instanceof a;case"Boolean":return"boolean"==typeof t;case"Number":case"Integer":case"Float":return"number"==typeof t}return-1!==e.indexOf("Texture")?Boolean(t.type):0!==e.indexOf("Array")||c.isArray(t)},getVariableType(e,t){if(c.isArray(e))return e.length>0&&"IMG"===e[0].nodeName?"HTMLImageArray":"Array";switch(e.constructor){case Boolean:return"Boolean";case Number:return t&&Number.isInteger(e)?"Integer":"Float";case o:return e.type;case a:return"Input"}if("nodeName"in e)switch(e.nodeName){case"IMG":case"CANVAS":return"HTMLImage";case"VIDEO":return"HTMLVideo"}else{if(e.hasOwnProperty("type"))return e.type;if("undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return"OffscreenCanvas";if("undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap)return"ImageBitmap";if("undefined"!=typeof ImageData&&e instanceof ImageData)return"ImageData"}return"Unknown"},getKernelTextureSize(e,t){let[r,n,s]=t,i=(r||1)*(n||1)*(s||1);return e.optimizeFloatMemory&&"single"===e.precision&&(r=i=Math.ceil(i/4)),n>1&&r*n===i?new Int32Array([r,n]):c.closestSquareDimensions(i)},closestSquareDimensions(e){const t=Math.sqrt(e);let r=Math.ceil(t),n=Math.floor(t);for(;r*nMath.floor((e+t-1)/t)*t,getDimensions(e,t){let r;if(c.isArray(e)){const t=[];let n=e;for(;c.isArray(n);)t.push(n.length),n=n[0];r=t.reverse()}else if(e instanceof o)r=e.output;else{if(!(e instanceof a))throw new Error(`Unknown dimensions of ${e}`);r=e.size}if(t)for(r=Array.from(r);r.length<3;)r.push(1);return new Int32Array(r)},flatten2dArrayTo(e,t){let r=0;for(let n=0;ne.length>0?e.join(";\n")+";\n":"\n",warnDeprecated(e,t,r){r?console.warn(`You are using a deprecated ${e} "${t}". It has been replaced with "${r}". Fixing, but please upgrade as it will soon be removed.`):console.warn(`You are using a deprecated ${e} "${t}". It has been removed. Fixing, but please upgrade as it will soon be removed.`)},flipPixels:(e,t,r)=>{const n=r/2|0,s=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee.subarray(0,t),erect2DPackedFloat:(e,t,r)=>{const n=new Array(r);for(let s=0;s{const s=new Array(n);for(let i=0;ie.subarray(0,t),erectMemoryOptimized2DFloat:(e,t,r)=>{const n=new Array(r);for(let s=0;s{const s=new Array(n);for(let i=0;i{const r=new Float32Array(t);let n=0;for(let s=0;s{const n=new Array(r);let s=0;for(let i=0;i{const s=new Array(n);let i=0;for(let a=0;a{const r=new Array(t),n=4*t;let s=0;for(let t=0;t{const n=new Array(r),s=4*t;for(let i=0;i{const s=4*t,i=new Array(n);for(let a=0;a{const r=new Array(t),n=4*t;let s=0;for(let t=0;t{const n=4*t,s=new Array(r);for(let i=0;i{const s=4*t,i=new Array(n);for(let a=0;a{const r=new Array(e),n=4*t;let s=0;for(let t=0;t{const n=4*t,s=new Array(r);for(let i=0;i{const s=4*t,i=new Array(n);for(let a=0;a{const{findDependency:r,thisLookup:n,doNotDefine:s}=t;let a=t.flattened;a||(a=t.flattened={});const o=i.parse(e,{ecmaVersion:2020}),u=[];let l=0;const h=function e(t){if(Array.isArray(t)){const r=[];for(let n=0;nnull!==e);return s.length<1?"":`${t.kind} ${s.join(",")}`;case"VariableDeclarator":return t.init?t.init.object&&"ThisExpression"===t.init.object.type?n(t.init.property.name,!0)?`${t.id.name} = ${e(t.init)}`:null:`${t.id.name} = ${e(t.init)}`:t.id.name;case"CallExpression":if("subarray"===t.callee.property.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("gl"===t.callee.object.name||"context"===t.callee.object.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("ThisExpression"===t.callee.object.type)return u.push(r("this",t.callee.property.name)),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;if(t.callee.object.name){const n=r(t.callee.object.name,t.callee.property.name);return null===n?`${t.callee.object.name}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`:(u.push(n),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`)}if("MemberExpression"===t.callee.object.type)return`${e(t.callee.object)}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;throw new Error("unknown ast.callee");case"ReturnStatement":return`return ${e(t.argument)}`;case"BinaryExpression":return`(${e(t.left)}${t.operator}${e(t.right)})`;case"UnaryExpression":return t.prefix?`${t.operator} ${e(t.argument)}`:`${e(t.argument)} ${t.operator}`;case"ExpressionStatement":return`${e(t.expression)}`;case"SequenceExpression":return`(${e(t.expressions)})`;case"ArrowFunctionExpression":return`(${t.params.map(e).join(", ")}) => ${e(t.body)}`;case"Literal":return t.raw;case"Identifier":return t.name;case"MemberExpression":return"ThisExpression"===t.object.type?n(t.property.name):t.computed?`${e(t.object)}[${e(t.property)}]`:e(t.object)+"."+e(t.property);case"ThisExpression":return"this";case"NewExpression":return`new ${e(t.callee)}(${t.arguments.map(t=>e(t)).join(", ")})`;case"ForStatement":return`for (${e(t.init)};${e(t.test)};${e(t.update)}) ${e(t.body)}`;case"AssignmentExpression":return`${e(t.left)}${t.operator}${e(t.right)}`;case"UpdateExpression":return`${e(t.argument)}${t.operator}`;case"IfStatement":{const r=e(t.consequent);if(!t.alternate)return`if (${e(t.test)}) ${r}`;const n="BlockStatement"===t.consequent.type?"":";";return`if (${e(t.test)}) ${r}${n} else ${e(t.alternate)}`}case"ThrowStatement":return`throw ${e(t.argument)}`;case"ObjectPattern":return t.properties.map(e).join(", ");case"ArrayPattern":return t.elements.map(e).join(", ");case"DebuggerStatement":return"debugger;";case"ConditionalExpression":return`${e(t.test)}?${e(t.consequent)}:${e(t.alternate)}`;case"Property":if("init"===t.kind)return e(t.key)}throw new Error(`unhandled ast.type of ${t.type}`)}(o);if(u.length>0){const e=[];for(let r=0;r{if("VariableDeclaration"!==e.type)throw new Error('Ast is not of type "VariableDeclaration"');const t=[];for(let r=0;r{const r=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].r},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),n=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].g},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),s=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].b},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),i=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].a},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),a=[r(t),n(t),s(t),i(t)];return a.rKernel=r,a.gKernel=n,a.bKernel=s,a.aKernel=i,a.gpu=e,a},splitRGBAToCanvases:(e,t,r,n)=>{const s=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(t.r/255,0,0,255)},{output:[r,n],graphical:!0,argumentTypes:{v:"Array2D(4)"}});s(t);const i=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,t.g/255,0,255)},{output:[r,n],graphical:!0,argumentTypes:{v:"Array2D(4)"}});i(t);const a=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,0,t.b/255,255)},{output:[r,n],graphical:!0,argumentTypes:{v:"Array2D(4)"}});a(t);const o=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(255,255,255,t.a/255)},{output:[r,n],graphical:!0,argumentTypes:{v:"Array2D(4)"}});return o(t),[s.canvas,i.canvas,a.canvas,o.canvas]},getMinifySafeName:e=>{try{const{init:t}=i.parse(`const value = ${e.toString()}`,{ecmaVersion:2020}).body[0].declarations[0];return t.body.name||t.body.body[0].argument.name}catch(e){throw new Error("Unrecognized function type. Please use `() => yourFunctionVariableHere` or function() { return yourFunctionVariableHere; }")}},sanitizeName:function(e){return p.test(e)&&(e=e.replace(p,"S_S")),d.test(e)?e=e.replace(d,"U_U"):f.test(e)&&(e=e.replace(f,"u_u")),e}},p=/\$/,d=/__/,f=/_/,m=c.getSystemEndianness();t.exports={utils:c}}),a=e((e,t)=>{const{utils:r}=i(),{Input:s}=n();t.exports={Kernel:class{static get isSupported(){throw new Error(`"isSupported" not implemented on ${this.name}`)}static isContextMatch(e){throw new Error(`"isContextMatch" not implemented on ${this.name}`)}static getFeatures(){throw new Error(`"getFeatures" not implemented on ${this.name}`)}static destroyContext(e){throw new Error(`"destroyContext" called on ${this.name}`)}static nativeFunctionArguments(){throw new Error(`"nativeFunctionArguments" called on ${this.name}`)}static nativeFunctionReturnType(){throw new Error(`"nativeFunctionReturnType" called on ${this.name}`)}static combineKernels(){throw new Error(`"combineKernels" called on ${this.name}`)}constructor(e,t){if("object"!=typeof e){if("string"!=typeof e)throw new Error("source not a string");if(!r.isFunctionString(e))throw new Error("source not a function string")}this.useLegacyEncoder=!1,this.fallbackRequested=!1,this.fallbackReason=null,this.onRequestFallback=null,this.onRequestSwitchKernel=null,this.argumentNames="string"==typeof e?r.getArgumentNamesFromString(e):null,this.argumentTypes=null,this.declaredArgumentTypes=null,this.argumentSizes=null,this.argumentBitRatios=null,this.kernelArguments=null,this.kernelConstants=null,this.forceUploadKernelConstants=null,this.source=e,this.output=null,this.debug=!1,this.graphical=!1,this.loopMaxIterations=0,this.constants=null,this.constantTypes=null,this.constantBitRatios=null,this.dynamicArguments=!1,this.dynamicOutput=!1,this.canvas=null,this.context=null,this.checkContext=null,this.gpu=null,this.functions=null,this.nativeFunctions=null,this.injectedNative=null,this.subKernels=null,this.validate=!0,this.immutable=!1,this.pipeline=!1,this.asyncMode=!1,this.precision=null,this.tactic=null,this.plugins=null,this.returnType=null,this.leadingReturnStatement=null,this.followingReturnStatement=null,this.optimizeFloatMemory=null,this.strictIntegers=!1,this.fixIntegerDivisionAccuracy=null,this.randomSeed=null,this.built=!1,this.signature=null,this.switchingKernels=null}mergeSettings(e){for(let t in e)if(e.hasOwnProperty(t)&&this.hasOwnProperty(t)){switch(t){case"argumentTypes":this.argumentTypes=e[t],e[t]&&(this.declaredArgumentTypes=Array.isArray(e[t])?e[t].slice():e[t]);continue;case"output":if(!Array.isArray(e.output)){this.setOutput(e.output);continue}break;case"functions":this.functions=[];for(let t=0;te.name):null,returnType:this.returnType}}}buildSignature(e){const t=this.constructor;this.signature=t.getSignature(this,t.getArgumentTypes(this,e))}static getArgumentTypes(e,t){const n=new Array(t.length);for(let s=0;st.argumentTypes[e])||[];const i=Object.keys(t.argumentTypes);if(i.length>0&&e.length>0&&s.every(e=>void 0===e))throw new Error(`argumentTypes keys [${i.join(", ")}] match none of the function's parameters [${e.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${i.map(e=>t.argumentTypes[e]).join("', '")}']`)}else s=t.argumentTypes||[];return{name:t.name||r.getFunctionNameFromString(n)||("function"==typeof e&&e.name?e.name:null),source:n,argumentTypes:s,returnType:t.returnType||null}}onActivate(e){}switchKernels(e){this.switchingKernels?this.switchingKernels.push(e):this.switchingKernels=[e]}resetSwitchingKernels(){const e=this.switchingKernels;return this.switchingKernels=null,e}checkArgumentTypes(e){if(!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let n=0;n{t.exports={FunctionBuilder:class e{static fromKernel(t,r,n){const{kernelArguments:s,kernelConstants:i,argumentNames:a,argumentSizes:o,argumentBitRatios:u,constants:l,constantBitRatios:h,debug:c,loopMaxIterations:p,nativeFunctions:d,output:f,optimizeFloatMemory:m,precision:g,plugins:y,source:x,subKernels:b,functions:v,leadingReturnStatement:T,followingReturnStatement:S,dynamicArguments:A,dynamicOutput:w}=t,_=new Array(s.length),E={};for(let e=0;eU.needsArgumentType(e,t),k=(e,t,r)=>{U.assignArgumentType(e,t,r)},L=(e,t,r)=>U.lookupReturnType(e,t,r),F=e=>U.lookupFunctionArgumentTypes(e),$=(e,t)=>U.lookupFunctionArgumentName(e,t),C=(e,t)=>U.lookupFunctionArgumentBitRatio(e,t),D=(e,t,r,n)=>{U.assignArgumentType(e,t,r,n)},G=(e,t,r,n)=>{U.assignArgumentBitRatio(e,t,r,n)},R=(e,t,r)=>{U.trackFunctionCall(e,t,r)},M=(e,t)=>{const n=[];for(let t=0;tnew r(e.source,{name:e.name||void 0,returnType:e.returnType,argumentTypes:e.argumentTypes,output:f,plugins:y,constants:l,constantTypes:E,constantBitRatios:h,optimizeFloatMemory:m,precision:g,lookupReturnType:L,lookupFunctionArgumentTypes:F,lookupFunctionArgumentName:$,lookupFunctionArgumentBitRatio:C,needsArgumentType:I,assignArgumentType:k,triggerImplyArgumentType:D,triggerImplyArgumentBitRatio:G,onFunctionCall:R,onNestedFunction:M})));let B=null;b&&(B=b.map(e=>{const{name:t,source:n}=e;return new r(n,Object.assign({},O,{name:t,isSubKernel:!0,isRootKernel:!1}))}));const U=new e({kernel:t,rootNode:z,functionNodes:V,nativeFunctions:d,subKernelNodes:B});return U}constructor(e){if(e=e||{},this.kernel=e.kernel,this.rootNode=e.rootNode,this.functionNodes=e.functionNodes||[],this.subKernelNodes=e.subKernelNodes||[],this.nativeFunctions=e.nativeFunctions||[],this.functionMap={},this.nativeFunctionNames=[],this.lookupChain=[],this.functionNodeDependencies={},this.functionCalls={},this.rootNode&&(this.functionMap.kernel=this.rootNode),this.functionNodes)for(let e=0;e-1){const r=t.indexOf(e);if(-1===r)t.push(e);else{const e=t.splice(r,1)[0];t.push(e)}return t}const r=this.functionMap[e];if(r){const n=t.indexOf(e);if(-1===n){t.push(e),r.toString();for(let e=0;e-1){t.push(this.nativeFunctions[s].source);continue}const i=this.functionMap[n];i&&t.push(i.toString())}return t}toJSON(){return this.traceFunctionCalls(this.rootNode.name).reverse().map(e=>{const t=this.nativeFunctions.indexOf(e);if(t>-1)return{name:e,source:this.nativeFunctions[t].source};if(this.functionMap[e])return this.functionMap[e].toJSON();throw new Error(`function ${e} not found`)})}fromJSON(e,t){this.functionMap={};for(let r=0;r0){const s=t.arguments;for(let t=0;t{const{utils:r}=i();function n(e){return e.length>0?e[e.length-1]:null}const s="trackIdentifiers",a="memberExpression",o="inForLoopInit";t.exports={FunctionTracer:class{constructor(e){this.runningContexts=[],this.functionContexts=[],this.contexts=[],this.functionCalls=[],this.declarations=[],this.identifiers=[],this.functions=[],this.returnStatements=[],this.trackedIdentifiers=null,this.states=[],this.newFunctionContext(),this.scan(e)}isState(e){return this.states[this.states.length-1]===e}hasState(e){return this.states.indexOf(e)>-1}pushState(e){this.states.push(e)}popState(e){if(!this.isState(e))throw new Error(`Cannot pop the non-active state "${e}"`);this.states.pop()}get currentFunctionContext(){return n(this.functionContexts)}get currentContext(){return n(this.runningContexts)}newFunctionContext(){const e={"@contextType":"function"};this.contexts.push(e),this.functionContexts.push(e)}newContext(e){const t=Object.assign({"@contextType":"const/let"},this.currentContext);this.contexts.push(t),this.runningContexts.push(t),e();const{currentFunctionContext:r}=this;for(const e in r)r.hasOwnProperty(e)&&!t.hasOwnProperty(e)&&(t[e]=r[e]);return this.runningContexts.pop(),t}useFunctionContext(e){const t=n(this.functionContexts);this.runningContexts.push(t),e(),this.runningContexts.pop()}getIdentifiers(e){const t=this.trackedIdentifiers=[];return this.pushState(s),e(),this.trackedIdentifiers=null,this.popState(s),t}getDeclaration(e){const{currentContext:t,currentFunctionContext:r,runningContexts:n}=this,s=t[e]||r[e]||null;if(!s&&t===r&&n.length>0){const t=n[n.length-2];if(t[e])return t[e]}return s}scan(e){if(e)if(Array.isArray(e))for(let t=0;t{this.scan(e.body)});break;case"BlockStatement":this.newContext(()=>{this.scan(e.body)});break;case"AssignmentExpression":case"LogicalExpression":case"BinaryExpression":this.scan(e.left),this.scan(e.right);break;case"UpdateExpression":if("++"===e.operator){const t=this.getDeclaration(e.argument.name);t&&(t.suggestedType="Integer")}this.scan(e.argument);break;case"UnaryExpression":this.scan(e.argument);break;case"VariableDeclaration":"var"===e.kind?this.useFunctionContext(()=>{e.declarations=r.normalizeDeclarations(e),this.scan(e.declarations)}):(e.declarations=r.normalizeDeclarations(e),this.scan(e.declarations));break;case"VariableDeclarator":{const{currentContext:t}=this,r=this.hasState(o),n={ast:e,context:t,name:e.id.name,origin:"declaration",inForLoopInit:r,inForLoopTest:null,assignable:t===this.currentFunctionContext||!r&&!t.hasOwnProperty(e.id.name),suggestedType:null,valueType:null,dependencies:null,isSafe:null};t[e.id.name]||(t[e.id.name]=n),this.declarations.push(n),this.scan(e.id),this.scan(e.init);break}case"FunctionExpression":case"FunctionDeclaration":0===this.runningContexts.length?this.scan(e.body):this.functions.push(e);break;case"IfStatement":this.scan(e.test),this.scan(e.consequent),e.alternate&&this.scan(e.alternate);break;case"ForStatement":{let t;const r=this.newContext(()=>{this.pushState(o),this.scan(e.init),this.popState(o),t=this.getIdentifiers(()=>{this.scan(e.test)}),this.scan(e.update),this.newContext(()=>{this.scan(e.body)})});if(t)for(const e in r)"@contextType"!==e&&t.indexOf(e)>-1&&(r[e].inForLoopTest=!0);break}case"DoWhileStatement":case"WhileStatement":this.newContext(()=>{this.scan(e.body),this.scan(e.test)});break;case"Identifier":this.isState(s)&&this.trackedIdentifiers.push(e.name),this.identifiers.push({context:this.currentContext,declaration:this.getDeclaration(e.name),ast:e});break;case"ReturnStatement":this.returnStatements.push(e),this.scan(e.argument);break;case"MemberExpression":this.pushState(a),this.scan(e.object),this.scan(e.property),this.popState(a);break;case"ExpressionStatement":this.scan(e.expression);break;case"SequenceExpression":this.scan(e.expressions);break;case"CallExpression":this.functionCalls.push({context:this.currentContext,ast:e}),this.scan(e.arguments);break;case"ArrayExpression":this.scan(e.elements);break;case"ConditionalExpression":this.scan(e.test),this.scan(e.alternate),this.scan(e.consequent);break;case"SwitchStatement":this.scan(e.discriminant),this.scan(e.cases);break;case"SwitchCase":this.scan(e.test),this.scan(e.consequent);break;case"ThisExpression":case"Literal":case"DebuggerStatement":case"EmptyStatement":case"BreakStatement":case"ContinueStatement":break;default:throw new Error(`unhandled type "${e.type}"`)}}}}}),l=e((e,t)=>{const n=r(),{utils:s}=i(),{FunctionTracer:a}=u(),o=["E","PI","SQRT2","SQRT1_2","LN2","LN10","LOG2E","LOG10E"],l=["abs","acos","acosh","asin","asinh","atan","atan2","atanh","cbrt","ceil","clz32","cos","cosh","expm1","exp","floor","fround","imul","log","log2","log10","log1p","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc"],h=["value","value[]","value[][]","value[][][]","value[][][][]","value.value","value.thread.value","this.thread.value","this.output.value","this.constants.value","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]","fn()[]","fn()[][]","fn()[][][]","[][]"];const c={Number:"Number",Float:"Float",Integer:"Integer",Array:"Number","Array(2)":"Number","Array(3)":"Number","Array(4)":"Number","Matrix(2)":"Number","Matrix(3)":"Number","Matrix(4)":"Number",Array2D:"Number",Array3D:"Number",Input:"Number",HTMLCanvas:"Array(4)",OffscreenCanvas:"Array(4)",HTMLImage:"Array(4)",ImageBitmap:"Array(4)",ImageData:"Array(4)",HTMLVideo:"Array(4)",HTMLImageArray:"Array(4)",NumberTexture:"Number",MemoryOptimizedNumberTexture:"Number","Array1D(2)":"Array(2)","Array1D(3)":"Array(3)","Array1D(4)":"Array(4)","Array2D(2)":"Array(2)","Array2D(3)":"Array(3)","Array2D(4)":"Array(4)","Array3D(2)":"Array(2)","Array3D(3)":"Array(3)","Array3D(4)":"Array(4)","ArrayTexture(1)":"Number","ArrayTexture(2)":"Array(2)","ArrayTexture(3)":"Array(3)","ArrayTexture(4)":"Array(4)"};let p=536870912;function d(e,t){return e.start=p++,e.end=p++,t&&t.loc&&(e.loc=t.loc),e}function f(e,t){return e&&e.body&&"BlockStatement"===e.body.type?(m(e.body,t),e):e}function m(e,t){e.body=g(e.body,t)}function g(e,t){const r=[];for(let n=0;n{if(!e||"object"!=typeof e||r)return e;if(Array.isArray(e))return e.map(n);switch(e.type){case"ContinueStatement":return e.label?(r=!0,e):d({type:"BlockStatement",body:[...S(t),e]},e);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionExpression":case"FunctionDeclaration":case"ArrowFunctionExpression":default:return e;case"IfStatement":return e.consequent=n(e.consequent),e.alternate&&(e.alternate=n(e.alternate)),e;case"BlockStatement":return e.body=e.body.map(n),e;case"SwitchStatement":for(let t=0;t0?(r.push(e),r):[e]}case"WhileStatement":case"DoWhileStatement":return e.body&&(e.body=x(e.body,t)),[e];case"SwitchStatement":for(let r=0;r0&&this.argumentTypes.length!==this.argumentNames.length)throw new Error(`argumentTypes count of ${this.argumentTypes.length} exceeds ${this.argumentNames.length}`);if(this.output.length<1)throw new Error("this.output is not big enough")}isIdentifierConstant(e){return!!this.constants&&this.constants.hasOwnProperty(e)}isInput(e){return"Input"===this.argumentTypes[this.argumentNames.indexOf(e)]}pushState(e){this.states.push(e)}popState(e){if(this.state!==e)throw new Error(`Cannot popState ${e} when in ${this.state}`);this.states.pop()}isState(e){return this.state===e}get state(){return this.states[this.states.length-1]}astMemberExpressionUnroll(e){if("Identifier"===e.type)return e.name;if("ThisExpression"===e.type)return"this";if("MemberExpression"===e.type&&e.object&&e.property)return e.object.hasOwnProperty("name")&&"Math"!==e.object.name?this.astMemberExpressionUnroll(e.property):this.astMemberExpressionUnroll(e.object)+"."+this.astMemberExpressionUnroll(e.property);if(e.hasOwnProperty("expressions")){const t=e.expressions[0];if("Literal"===t.type&&0===t.value&&2===e.expressions.length)return this.astMemberExpressionUnroll(e.expressions[1])}throw this.astErrorOutput("Unknown astMemberExpressionUnroll",e)}get requiresSequenceFreeForInit(){return!1}getJsAST(e){if(this.ast)return this.ast;if("object"==typeof this.source)return f(this.source,this.requiresSequenceFreeForInit),this.traceFunctionAST(this.source),this.ast=this.source;if(null===(e=e||n))throw new Error("Missing JS to AST parser");const t=Object.freeze(e.parse(`const parser_${this.name} = ${this.source};`,{locations:!0,ecmaVersion:2020})),r=t.body[0].declarations[0].init;if(f(r,this.requiresSequenceFreeForInit),this.traceFunctionAST(r),!t)throw new Error("Failed to parse JS code");return this.ast=r}getAssignedArguments(){if(this._assignedArguments)return this._assignedArguments;const e=new Set,t=new Set,r=this.argumentNames||[],n=s=>{if(s&&"object"==typeof s)if(Array.isArray(s))for(const e of s)n(e);else{"AssignmentExpression"===s.type&&"Identifier"===s.left.type&&-1!==r.indexOf(s.left.name)&&e.add(s.left.name),"UpdateExpression"===s.type&&"Identifier"===s.argument.type&&-1!==r.indexOf(s.argument.name)&&e.add(s.argument.name),"VariableDeclarator"===s.type&&"Identifier"===s.id.type&&-1!==r.indexOf(s.id.name)&&t.add(s.id.name);for(const e in s){if("loc"===e||"range"===e||"parent"===e)continue;const t=s[e];t&&"object"==typeof t&&n(t)}}};n(this.getJsAST());for(const r of t)e.delete(r);return this._assignedArguments=e}traceFunctionAST(e){const{contexts:t,declarations:r,functions:n,identifiers:s,functionCalls:i}=new a(e);this.contexts=t,this.identifiers=s,this.functionCalls=i,this.functions=n;for(let e=0;e":case"<":return"Boolean";case"&":case"|":case"^":case"<<":case">>":case">>>":return"Integer"}const r=this.getType(e.left);if(this.isState("skip-literal-correction"))return r;if("LiteralInteger"===r){const t=this.getType(e.right);return"LiteralInteger"===t?e.left.value%1==0?"Integer":"Float":t}if("Integer"===r){const t=this.getType(e.right);if("Number"===t||"Float"===t)return t}return c[r]||r;case"UpdateExpression":case"ReturnStatement":return this.getType(e.argument);case"UnaryExpression":return"~"===e.operator?"Integer":this.getType(e.argument);case"VariableDeclaration":{const t=e.declarations;let r;for(let e=0;ee.isSafe)}getDependencies(e,t,r){if(t||(t=[]),!e)return null;if(Array.isArray(e)){for(let n=0;n-1/0&&e.value<1/0&&!isNaN(e.value))});break;case"VariableDeclarator":return this.getDependencies(e.init,t,r);case"Identifier":const n=this.getDeclaration(e);if(n)t.push({name:e.name,origin:"declaration",isSafe:!r&&this.isSafeDependencies(n.dependencies)});else if(this.argumentNames.indexOf(e.name)>-1)t.push({name:e.name,origin:"argument",isSafe:!1});else if(this.strictTypingChecking)throw new Error(`Cannot find identifier origin "${e.name}"`);break;case"FunctionDeclaration":return this.getDependencies(e.body.body[e.body.body.length-1],t,r);case"ReturnStatement":return this.getDependencies(e.argument,t);case"BinaryExpression":case"LogicalExpression":return r="/"===e.operator||"*"===e.operator,this.getDependencies(e.left,t,r),this.getDependencies(e.right,t,r),t;case"UnaryExpression":case"UpdateExpression":return this.getDependencies(e.argument,t,r);case"VariableDeclaration":return this.getDependencies(e.declarations,t,r);case"ArrayExpression":return t.push({origin:"declaration",isSafe:!0}),t;case"CallExpression":return t.push({origin:"function",isSafe:!0}),t;case"MemberExpression":const s=this.getMemberExpressionDetails(e);switch(s.signature){case"value[]":this.getDependencies(e.object,t,r);break;case"value[][]":this.getDependencies(e.object.object,t,r);break;case"value[][][]":this.getDependencies(e.object.object.object,t,r);break;case"this.output.value":this.dynamicOutput&&t.push({name:s.name,origin:"output",isSafe:!1})}if(s)return s.property&&this.getDependencies(s.property,t,r),s.xProperty&&this.getDependencies(s.xProperty,t,r),s.yProperty&&this.getDependencies(s.yProperty,t,r),s.zProperty&&this.getDependencies(s.zProperty,t,r),t;case"SequenceExpression":return this.getDependencies(e.expressions,t,r);default:throw this.astErrorOutput(`Unhandled type ${e.type} in getDependencies`,e)}return t}getVariableSignature(e,t){if(!this.isAstVariable(e))throw new Error(`ast of type "${e.type}" is not a variable signature`);if("Identifier"===e.type)return"value";const r=[];for(;e;)e.computed?r.push("[]"):"ThisExpression"===e.type?r.unshift("this"):e.property&&e.property.name?"x"===e.property.name||"y"===e.property.name||"z"===e.property.name?r.unshift(t?"."+e.property.name:".value"):"constants"===e.property.name||"thread"===e.property.name||"output"===e.property.name?r.unshift("."+e.property.name):r.unshift(t?"."+e.property.name:".value"):e.name?r.unshift(t?e.name:"value"):e.callee&&e.callee.name?r.unshift(t?e.callee.name+"()":"fn()"):e.elements?r.unshift("[]"):r.unshift("unknown"),e=e.object;const n=r.join("");return t||h.includes(n)?n:null}build(){return this.toString().length>0}astGeneric(e,t){if(null===e)throw this.astErrorOutput("NULL ast",e);if(Array.isArray(e)){for(let r=0;r0?n[n.length-1]:0;return new Error(`${e} on line ${n.length}, position ${i.length}:\n ${r}`)}astDebuggerStatement(e,t){return t}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);return t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t}astFunction(e,t){throw new Error(`"astFunction" not defined on ${this.constructor.name}`)}astFunctionDeclaration(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}astFunctionExpression(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}isChildFunction(e){for(let t=0;t1?t.push("(",n.join(","),")"):t.push(n[0]),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)||(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator))),t}checkAndUpconvertBitwiseUnary(e,t){}astUpdateExpression(e,t){return e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t}astLogicalExpression(e,t){return t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),t.push(")"),t}astMemberExpression(e,t){return t}astCallExpression(e,t){return t}astArrayExpression(e,t){return t}getMemberExpressionDetails(e){if("MemberExpression"!==e.type)throw this.astErrorOutput(`Expression ${e.type} not a MemberExpression`,e);let t=null,r=null;const n=this.getVariableSignature(e);switch(n){case"value":return null;case"value.thread.value":case"this.thread.value":case"this.output.value":return{signature:n,type:"Integer",name:e.property.name};case"value[]":if("string"!=typeof e.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.name,{name:t,origin:"user",signature:n,type:this.getVariableType(e.object),xProperty:e.property};case"value[][]":if("string"!=typeof e.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.name,{name:t,origin:"user",signature:n,type:this.getVariableType(e.object.object),yProperty:e.object.property,xProperty:e.property};case"value[][][]":if("string"!=typeof e.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.name,{name:t,origin:"user",signature:n,type:this.getVariableType(e.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value[][][][]":if("string"!=typeof e.object.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.object.name,{name:t,origin:"user",signature:n,type:this.getVariableType(e.object.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(this.isAstMathVariable(e))return t=e.property.name,{name:t,origin:"Math",type:"Number",signature:n};switch(e.property.name){case"r":case"g":case"b":case"a":return t=e.object.name,{name:t,property:e.property.name,origin:"user",signature:n,type:"Number"};default:throw this.astErrorOutput("Unexpected expression",e)}case"this.constants.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:n};case"this.constants.value[]":if("string"!=typeof e.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:n,xProperty:e.property};case"this.constants.value[][]":if("string"!=typeof e.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:n,yProperty:e.object.property,xProperty:e.property};case"this.constants.value[][][]":if("string"!=typeof e.object.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:n,zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"fn()[]":case"fn()[][]":case"[][]":return{signature:n,property:e.property};default:throw this.astErrorOutput("Unexpected expression",e)}}findIdentifierOrigin(e){const t=[this.ast];for(;t.length>0;){const r=t[0];if("VariableDeclarator"===r.type&&r.id&&r.id.name&&r.id.name===e.name)return r;if(t.shift(),r.argument)t.push(r.argument);else if(r.body)t.push(r.body);else if(r.declarations)t.push(r.declarations);else if(Array.isArray(r))for(let e=0;e0;){const e=t.pop();if("ReturnStatement"===e.type)return e;if("FunctionDeclaration"!==e.type)if(e.argument)t.push(e.argument);else if(e.body)t.push(e.body);else if(e.declarations)t.push(e.declarations);else if(Array.isArray(e))for(let r=0;r{const{FunctionNode:r}=l();t.exports={CPUFunctionNode:class extends r{markupUserName(e){return this.isRootKernel&&this.getAssignedArguments().has(e)?`cellShadow_user_${e}`:`user_${e}`}astFunction(e,t){if(!this.isRootKernel){t.push("function"),t.push(" "),t.push(this.name),t.push("(");for(let e=0;e0&&t.push(", "),t.push("user_"),t.push(r)}t.push(") {\n")}if(this.isRootKernel){for(const e of this.getAssignedArguments())t.push(`let cellShadow_user_${e} = user_${e};\n`);t.push("kernelBody: {\n")}for(let r=0;r0&&t.push(r.join(""),";\n"),t.push(`for (let ${e}=0;${e}0&&t.push(`if (!${n.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);return t.push("for (let i = 0; i < LOOP_MAX; i++) {"),t.push("if ("),this.astGeneric(e.test,t),t.push(") {\n"),this.astGeneric(e.body,t),t.push("} else {\n"),t.push("break;\n"),t.push("}\n"),t.push("}\n"),t}astDoWhileStatement(e,t){if("DoWhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=`safeI${this.astKey(e,"_")}`;return t.push(`let ${r} = 0;\n`),t.push("do {"),this.astGeneric(e.body,t),t.push("} while (("),this.astGeneric(e.test,t),t.push(`) && ++${r} < LOOP_MAX);\n`),t}astAssignmentExpression(e,t){const r=this.isState("assignment-as-statement");return r?this.popState("assignment-as-statement"):t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),r||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let r=0;r0&&t.push(",");const n=r[e],s=this.getDeclaration(n.id);s.valueType||(s.valueType=this.getType(n.init)),this.astGeneric(n,t)}return this.isState("in-for-loop-init")||t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchStatement(e,t){const{discriminant:r,cases:n}=e;t.push("switch ("),this.astGeneric(r,t),t.push(") {\n");for(let e=0;e0&&(this.astGeneric(n[e].consequent,t),t.push("break;\n"))):(t.push("default:\n"),this.astGeneric(n[e].consequent,t),n[e].consequent&&n[e].consequent.length>0&&t.push("break;\n"));t.push("\n}")}astThisExpression(e,t){return t.push("_this"),t}astMemberExpression(e,t){const{signature:r,type:n,property:s,xProperty:i,yProperty:a,zProperty:o,name:u,origin:l}=this.getMemberExpressionDetails(e);switch(r){case"this.thread.value":return t.push(`_this.thread.${u}`),t;case"this.output.value":switch(u){case"x":t.push("outputX");break;case"y":t.push("outputY");break;case"z":t.push("outputZ");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":default:throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value.value":if("Math"===l)return t.push(Math[u]),t;switch(s){case"r":return t.push(`user_${u}[0]`),t;case"g":return t.push(`user_${u}[1]`),t;case"b":return t.push(`user_${u}[2]`),t;case"a":return t.push(`user_${u}[3]`),t}break;case"this.constants.value":case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":break;case"fn()[]":return this.astGeneric(e.object,t),t.push("["),this.astGeneric(e.property,t),t.push("]"),t;case"fn()[][]":return this.astGeneric(e.object.object,t),t.push("["),this.astGeneric(e.object.property,t),t.push("]"),t.push("["),this.astGeneric(e.property,t),t.push("]"),t}if(!e.computed)switch(n){case"Number":case"Integer":case"Float":case"Boolean":return t.push("user"===l?this.markupUserName(u):`${l}_${u}`),t}const h="user"===l?this.markupUserName(u):`${l}_${u}`;{let e,r;if("constants"===l){const t=this.constants[u];r="Input"===this.constantTypes[u],e=r?t.size:null}else r=this.isInput(u),e=r?this.argumentSizes[this.argumentNames.indexOf(u)]:null;t.push(`${h}`),o&&a?r?(t.push("[("),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"(outputY * outputX)":e[1]*e[0]})+(`),this.astGeneric(a,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(i,t),t.push("]")):(t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]"),t.push("["),this.astGeneric(i,t),t.push("]")):a?r?(t.push("[("),this.astGeneric(a,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(i,t),t.push("]")):(t.push("["),this.astGeneric(a,t),t.push("]"),t.push("["),this.astGeneric(i,t),t.push("]")):void 0!==i&&(t.push("["),this.astGeneric(i,t),t.push("]"))}return t}astCallExpression(e,t){if("CallExpression"!==e.type)throw this.astErrorOutput("Unknown CallExpression",e);let r=this.astMemberExpressionUnroll(e.callee);this.calledFunctions.indexOf(r)<0&&this.calledFunctions.push(r),this.isAstMathFunction(e),this.onFunctionCall&&this.onFunctionCall(this.name,r,e.arguments),t.push(r),t.push("(");const n=this.lookupFunctionArgumentTypes(r)||[];for(let s=0;s0&&t.push(", "),this.astGeneric(i,t)}return t.push(")"),t}astArrayExpression(e,t){const r=this.getType(e),n=e.elements.length,s=[];for(let t=0;t{const{utils:r}=i();t.exports={cpuKernelString:function(e,t){const n=[],s=[],i=[],a=!/^function/.test(e.color.toString());if(n.push(" const { context, canvas, constants: incomingConstants } = settings;",` const output = new Int32Array(${JSON.stringify(Array.from(e.output))});`,` const _constantTypes = ${JSON.stringify(e.constantTypes)};`,` const _constants = ${function(e,t){const r=[];for(const n in t){if(!t.hasOwnProperty(n))continue;const s=t[n],i=e[n];switch(s){case"Number":case"Integer":case"Float":case"Boolean":r.push(`${n}:${i}`);break;case"Array(2)":case"Array(3)":case"Array(4)":case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":r.push(`${n}:new ${i.constructor.name}(${JSON.stringify(Array.from(i))})`)}}return`{ ${r.join()} }`}(e.constants,e.constantTypes)};`),s.push(" constants: _constants,"," context,"," output,"," thread: {x: 0, y: 0, z: 0},"),e.graphical){n.push(` const _imageData = context.createImageData(${e.output[0]}, ${e.output[1]});`),n.push(` const _colorData = new Uint8ClampedArray(${e.output[0]} * ${e.output[1]} * 4);`);const t=r.flattenFunctionToString((a?"function ":"")+e.color.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:(e,t)=>null}),o=r.flattenFunctionToString((a?"function ":"")+e.getPixels.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:()=>null});s.push(" _imageData,"," _colorData,",` color: ${t},`),i.push(` kernel.getPixels = ${o};`)}const o=[],u=Object.keys(e.constantTypes);for(let t=0;t"this"===t?(a?"function ":"")+e[r].toString():null,thisLookup:e=>{switch(e){case"canvas":return;case"context":return"context"}}});i.push(t),s.push(" _mediaTo2DArray,"),s.push(" _imageTo3DArray,")}else if(-1!==e.argumentTypes.indexOf("HTMLImage")||-1!==o.indexOf("HTMLImage")){const t=r.flattenFunctionToString((a?"function ":"")+e._mediaTo2DArray.toString(),{findDependency:(e,t)=>null,thisLookup:e=>{switch(e){case"canvas":return"settings.canvas";case"context":return"settings.context"}throw new Error("unhandled thisLookup")}});i.push(t),s.push(" _mediaTo2DArray,")}return`function(settings) {\n${n.join("\n")}\n for (const p in _constantTypes) {\n if (!_constantTypes.hasOwnProperty(p)) continue;\n const type = _constantTypes[p];\n switch (type) {\n case 'Number':\n case 'Integer':\n case 'Float':\n case 'Boolean':\n case 'Array(2)':\n case 'Array(3)':\n case 'Array(4)':\n case 'Matrix(2)':\n case 'Matrix(3)':\n case 'Matrix(4)':\n if (incomingConstants.hasOwnProperty(p)) {\n console.warn('constant ' + p + ' of type ' + type + ' cannot be resigned');\n }\n continue;\n }\n if (!incomingConstants.hasOwnProperty(p)) {\n throw new Error('constant ' + p + ' not found');\n }\n _constants[p] = incomingConstants[p];\n }\n const kernel = (function() {\n${e._kernelString}\n })\n .apply({ ${s.join("\n")} });\n ${i.join("\n")}\n return kernel;\n}`}}}),p=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:n}=o(),{CPUFunctionNode:s}=h(),{utils:u}=i(),{cpuKernelString:l}=c();t.exports={CPUKernel:class extends r{static getFeatures(){return this.features}static get features(){return Object.freeze({kernelMap:!0,isIntegerDivisionAccurate:!0})}static get isSupported(){return!0}static isContextMatch(e){return!1}static get mode(){return"cpu"}static nativeFunctionArguments(){return null}static nativeFunctionReturnType(){throw new Error(`Looking up native function return type not supported on ${this.name}`)}static combineKernels(e){return e}static getSignature(e,t){return"cpu"+(t.length>0?":"+t.join(","):"")}constructor(e,t){super(e,t),this.mergeSettings(e.settings||t),this._imageData=null,this._colorData=null,this._kernelString=null,this._prependedString=[],this.thread={x:0,y:0,z:0},this.translatedSources=null}initCanvas(){return"undefined"!=typeof document?document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(0,0):void 0}initContext(){return this.canvas?this.canvas.getContext("2d",{willReadFrequently:!0}):null}initPlugins(e){return[]}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=u.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=u.getDimensions(t);else{if("NumberTexture"!==t&&"ArrayTexture(4)"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=e[0].output}}if(this.graphical&&2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");this.checkOutput()}translateSource(){if(this.leadingReturnStatement=this.output.length>1?"resultX[x] = ":"result[x] = ",this.subKernels){const e=[];for(let t=0;t1?`resultX_${r}[x] = subKernelResult_${r};\n`:`result_${r}[x] = subKernelResult_${r};\n`)}this.followingReturnStatement=e.join("")}const e=n.fromKernel(this,s);this.translatedSources=e.getPrototypes("kernel"),this.graphical||this.returnType||(this.returnType=e.getKernelResultType())}build(){if(this.built)return;if(null!==this.randomSeed&&console.warn("randomSeed is not supported in cpu mode; Math.random() will be unseeded"),this.setupConstants(),this.setupArguments(arguments),this.validateSettings(arguments),this.translateSource(),this.graphical){const{canvas:e,output:t}=this;if(!e)throw new Error("no canvas available for using graphical output");const r=t[0],n=t[1]||1;e.width=r,e.height=n,this._imageData=this.context.createImageData(r,n),this._colorData=new Uint8ClampedArray(r*n*4)}const e=this.getKernelString();this.kernelString=e,this.debug&&(console.log("Function output:"),console.log(e));try{this.run=new Function([],e).bind(this)()}catch(e){console.error("An error occurred compiling the javascript: ",e)}this.buildSignature(arguments),this.built=!0}color(e,t,r,n){void 0===n&&(n=1),e=Math.floor(255*e),t=Math.floor(255*t),r=Math.floor(255*r),n=Math.floor(255*n);const s=this.output[0],i=this.output[1],a=this.thread.x+(i-this.thread.y-1)*s;this._colorData[4*a+0]=e,this._colorData[4*a+1]=t,this._colorData[4*a+2]=r,this._colorData[4*a+3]=n}getKernelString(){if(null!==this._kernelString)return this._kernelString;let e=null,{translatedSources:t}=this;return t.length>1?t=t.filter(t=>/^function/.test(t)?t:(e=t,!1)):e=t.shift(),this._kernelString=` const LOOP_MAX = ${this._getLoopMaxString()};\n ${this.injectedNative||""}\n const _this = this;\n ${this._resultKernelHeader()}\n ${this._processConstants()}\n return (${this.argumentNames.map(e=>"user_"+e).join(", ")}) => {\n ${this._prependedString.join("")}\n ${this._earlyThrows()}\n ${this._processArguments()}\n ${this.graphical?this._graphicalKernelBody(e):this._resultKernelBody(e)}\n ${t.length>0?t.join("\n"):""}\n };`}toString(){return l(this)}_getLoopMaxString(){return this.loopMaxIterations?` ${parseInt(this.loopMaxIterations)};`:" 1000;"}_processConstants(){if(!this.constants)return"";const e=[];for(let t in this.constants)switch(this.constantTypes[t]){case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":e.push(` const constants_${t} = this._mediaTo2DArray(this.constants.${t});\n`);break;case"HTMLImageArray":e.push(` const constants_${t} = this._imageTo3DArray(this.constants.${t});\n`);break;case"Input":e.push(` const constants_${t} = this.constants.${t}.value;\n`);break;default:e.push(` const constants_${t} = this.constants.${t};\n`)}return e.join("")}_earlyThrows(){if(this.graphical)return"";if(this.immutable)return"";if(!this.pipeline)return"";const e=[];for(let t=0;t`user_${n} === result_${e.name}`).join(" || ");t.push(`user_${n} === result${s?` || ${s}`:""}`)}return`if (${t.join(" || ")}) throw new Error('Source and destination arrays are the same. Use immutable = true');`}_processArguments(){const e=[];for(let t=0;t0?e.width:e.videoWidth,n=e.height>0?e.height:e.videoHeight;t.width=0;e--){const t=a[e]=new Array(r);for(let e=0;e`const result_${e.name} = new ${t}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_mutableKernel1DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const result = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const result_${t.name} = new ${e}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}`}_resultMutableKernel1DLoop(e){return` const outputX = _this.output[0];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_resultImmutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_mutableKernel2DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = result[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = result_${t.name}[y] = new ${e}(outputX);\n`).join("")}\n }`}_resultMutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y];\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_graphicalKernel2DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_resultImmutableKernel3DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = resultY_${e.name}[y] = new ${t}(outputX);\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_mutableKernel3DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = resultY[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = resultY_${t.name}[y] = new ${e}(outputX);\n`).join(" ")}\n }\n }`}_resultMutableKernel3DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z];\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_kernelOutput(){return this.subKernels?`\n return {\n result: result,\n ${this.subKernels.map(e=>`${e.property}: result_${e.name}`).join(",\n ")}\n };`:"\n return result;"}_mapSubKernels(e){return null===this.subKernels?[""]:this.subKernels.map(e)}destroy(e){e&&delete this.canvas}static destroyContext(e){}toJSON(){const e=super.toJSON();return e.functionNodes=n.fromKernel(this,s).toJSON(),e}setOutput(e){super.setOutput(e);const[t,r]=this.output;this.graphical&&(this._imageData=this.context.createImageData(t,r),this._colorData=new Uint8ClampedArray(t*r*4))}prependString(e){if(this._kernelString)throw new Error("Kernel already built");this._prependedString.push(e)}hasPrependString(e){return this._prependedString.indexOf(e)>-1}}}}),d=e((e,t)=>{const{Texture:r}=s();function n(e,t){e.activeTexture(e.TEXTURE15),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST)}t.exports={GLTexture:class extends r{get textureType(){throw new Error(`"textureType" not implemented on ${this.name}`)}clone(){return new this.constructor(this)}beforeMutate(){return this.texture._refs>1&&(this.newTexture(),!0)}cloneTexture(){this.texture._refs--;const{context:e,size:t,texture:r,kernel:s}=this;s.debug&&console.warn("cloning internal texture"),e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),n(e,r),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,r,0);const i=e.createTexture();n(e,i),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t[0],t[1]),i._refs=1,this.texture=i}newTexture(){this.texture._refs--;const e=this.context,t=this.size;this.kernel.debug&&console.warn("new internal texture");const r=e.createTexture();n(e,r),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),r._refs=1,this.texture=r}clear(){if(this.texture._refs){this.texture._refs--;const e=this.context,t=this.texture=e.createTexture();n(e,t);const r=this.size;t._refs=1,e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,r[0],r[1],0,this.textureFormat,this.textureType,null)}const{context:e,texture:t}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.bindTexture(e.TEXTURE_2D,t),n(e,t),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}delete(){this._deleted||(this._deleted=!0,this.texture._refs&&(this.texture._refs--,this.texture._refs)||(this.kernel&&this.kernel.deleteTexture?this.kernel.deleteTexture(this.texture):this.context.deleteTexture(this.texture)))}framebuffer(){return this._framebuffer||(this._framebuffer=this.kernel.getRawValueFramebuffer(this.size[0],this.size[1])),this._framebuffer}}}}),f=e((e,t)=>{const{utils:r}=i(),{GLTexture:n}=d();t.exports={GLTextureFloat:class extends n{get textureType(){return this.context.FLOAT}constructor(e){super(e),this.type="ArrayTexture(1)"}renderRawOutput(){const e=this.context,t=this.size;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const r=new Float32Array(t[0]*t[1]*4);return e.readPixels(0,0,t[0],t[1],e.RGBA,e.FLOAT,r),r}renderValues(){return this._deleted?null:this.renderRawOutput()}toArray(){return r.erectFloat(this.renderValues(),this.output[0])}}}}),m=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray2Float:class extends n{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erectArray2(this.renderValues(),this.output[0],this.output[1])}}}}),g=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray2Float2D:class extends n{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erect2DArray2(this.renderValues(),this.output[0],this.output[1])}}}}),y=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray2Float3D:class extends n{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erect3DArray2(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),x=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray3Float:class extends n{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erectArray3(this.renderValues(),this.output[0])}}}}),b=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray3Float2D:class extends n{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erect2DArray3(this.renderValues(),this.output[0],this.output[1])}}}}),v=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray3Float3D:class extends n{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erect3DArray3(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),T=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray4Float:class extends n{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erectArray4(this.renderValues(),this.output[0])}}}}),S=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray4Float2D:class extends n{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erect2DArray4(this.renderValues(),this.output[0],this.output[1])}}}}),A=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureArray4Float3D:class extends n{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erect3DArray4(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),w=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureFloat2D:class extends n{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return r.erect2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),_=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureFloat3D:class extends n{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return r.erect3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),E=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureMemoryOptimized:class extends n{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimizedFloat(this.renderValues(),this.output[0])}}}}),I=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureMemoryOptimized2D:class extends n{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimized2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),k=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:n}=f();t.exports={GLTextureMemoryOptimized3D:class extends n{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimized3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),L=e((e,t)=>{const{utils:r}=i(),{GLTexture:n}=d();t.exports={GLTextureUnsigned:class extends n{get textureType(){return this.context.UNSIGNED_BYTE}constructor(e){super(e),this.type="NumberTexture"}renderRawOutput(){const{context:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const t=new Uint8Array(this.size[0]*this.size[1]*4);return e.readPixels(0,0,this.size[0],this.size[1],e.RGBA,e.UNSIGNED_BYTE,t),t}renderValues(){return this._deleted?null:new Float32Array(this.renderRawOutput().buffer)}toArray(){return r.erectPackedFloat(this.renderValues(),this.output[0])}}}}),F=e((e,t)=>{const{utils:r}=i(),{GLTextureUnsigned:n}=L();t.exports={GLTextureUnsigned2D:class extends n{constructor(e){super(e),this.type="NumberTexture"}toArray(){return r.erect2DPackedFloat(this.renderValues(),this.output[0],this.output[1])}}}}),$=e((e,t)=>{const{utils:r}=i(),{GLTextureUnsigned:n}=L();t.exports={GLTextureUnsigned3D:class extends n{constructor(e){super(e),this.type="NumberTexture"}toArray(){return r.erect3DPackedFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),C=e((e,t)=>{const{GLTextureUnsigned:r}=L();t.exports={GLTextureGraphical:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return this.renderValues()}}}}),D=e((e,t)=>{const{Kernel:r}=a(),{utils:n}=i(),{GLTextureArray2Float:s}=m(),{GLTextureArray2Float2D:o}=g(),{GLTextureArray2Float3D:u}=y(),{GLTextureArray3Float:l}=x(),{GLTextureArray3Float2D:h}=b(),{GLTextureArray3Float3D:c}=v(),{GLTextureArray4Float:p}=T(),{GLTextureArray4Float2D:d}=S(),{GLTextureArray4Float3D:D}=A(),{GLTextureFloat:G}=f(),{GLTextureFloat2D:R}=w(),{GLTextureFloat3D:M}=_(),{GLTextureMemoryOptimized:O}=E(),{GLTextureMemoryOptimized2D:N}=I(),{GLTextureMemoryOptimized3D:z}=k(),{GLTextureUnsigned:V}=L(),{GLTextureUnsigned2D:B}=F(),{GLTextureUnsigned3D:U}=$(),{GLTextureGraphical:K}=C();const P={int:"Integer",float:"Number",vec2:"Array(2)",vec3:"Array(3)",vec4:"Array(4)"};t.exports={GLKernel:class extends r{static get mode(){return"gpu"}static getIsFloatRead(){const e=new this("function kernelFunction() {\n return 1;\n }",{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[1],precision:"single",returnType:"Number",tactic:"speed"});e.build(),e.run();const t=e.renderOutput();return e.destroy(!0),1===t[0]}static getIsIntegerDivisionAccurate(){const e=new this(function(e,t){return e[this.thread.x]/t[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[2],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[6,6030401],[3,3991]];e.build.apply(e,t),e.run.apply(e,t);const r=e.renderOutput();return e.destroy(!0),2===r[0]&&1511===r[1]}static getIsSpeedTacticSupported(){const e=new this(function(e){return e[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[4],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[0,1,2,3]];e.build.apply(e,t),e.run.apply(e,t);const r=e.renderOutput();return e.destroy(!0),0===Math.round(r[0])&&1===Math.round(r[1])&&2===Math.round(r[2])&&3===Math.round(r[3])}static get testCanvas(){throw new Error(`"testCanvas" not defined on ${this.name}`)}static get testContext(){throw new Error(`"testContext" not defined on ${this.name}`)}static getFeatures(){const e=this.testContext,t=this.getIsDrawBuffers();return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),isTextureFloat:this.getIsTextureFloat(),isDrawBuffers:t,kernelMap:t,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static setupFeatureChecks(){throw new Error(`"setupFeatureChecks" not defined on ${this.name}`)}static getSignature(e,t){return e.getVariablePrecisionString()+(t.length>0?":"+t.join(","):"")}setFixIntegerDivisionAccuracy(e){return this.fixIntegerDivisionAccuracy=e,this}setPrecision(e){return this.precision=e,this}setFloatTextures(e){return n.warnDeprecated("method","setFloatTextures","setOptimizeFloatMemory"),this.floatTextures=e,this}static nativeFunctionArguments(e){const t=[],r=[],n=[],s=/^[a-zA-Z_]/,i=/[a-zA-Z_0-9]/;let a=0,o=null,u=null;for(;a0?n[n.length-1]:null;if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"*"!==h)if("MULTI_LINE_COMMENT"!==c||"*"!==l||"/"!==h)if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"/"!==h)if("COMMENT"!==c||"\n"!==l)if(null!==c||"("!==l){if("FUNCTION_ARGUMENTS"===c){if(")"===l){n.pop();break}if("f"===l&&"l"===h&&"o"===e[a+2]&&"a"===e[a+3]&&"t"===e[a+4]&&" "===e[a+5]){n.push("DECLARE_VARIABLE"),u="float",o="",a+=6;continue}if("i"===l&&"n"===h&&"t"===e[a+2]&&" "===e[a+3]){n.push("DECLARE_VARIABLE"),u="int",o="",a+=4;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"2"===e[a+3]&&" "===e[a+4]){n.push("DECLARE_VARIABLE"),u="vec2",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"3"===e[a+3]&&" "===e[a+4]){n.push("DECLARE_VARIABLE"),u="vec3",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"4"===e[a+3]&&" "===e[a+4]){n.push("DECLARE_VARIABLE"),u="vec4",o="",a+=5;continue}}else if("DECLARE_VARIABLE"===c){if(""===o){if(" "===l){a++;continue}if(!s.test(l))throw new Error("variable name is not expected string")}o+=l,i.test(h)||(n.pop(),r.push(o),t.push(P[u]))}a++}else n.push("FUNCTION_ARGUMENTS"),a++;else n.pop(),a++;else n.push("COMMENT"),a+=2;else n.pop(),a+=2;else n.push("MULTI_LINE_COMMENT"),a+=2}if(n.length>0)throw new Error("GLSL function was not parsable");return{argumentNames:r,argumentTypes:t}}static nativeFunctionReturnType(e){return P[e.match(/int|float|vec[2-4]/)[0]]}static combineKernels(e,t){e.apply(null,arguments);const{texSize:r,context:s,threadDim:i}=t.texSize;let a;if("single"===t.precision){const e=r[0],t=Math.ceil(r[1]/4);a=new Float32Array(e*t*4*4),s.readPixels(0,0,e,4*t,s.RGBA,s.FLOAT,a)}else{const e=new Uint8Array(r[0]*r[1]*4);s.readPixels(0,0,r[0],r[1],s.RGBA,s.UNSIGNED_BYTE,e),a=new Float32Array(e.buffer)}return a=a.subarray(0,i[0]*i[1]*i[2]),1===t.output.length?a:2===t.output.length?n.splitArray(a,t.output[0]):3===t.output.length?n.splitArray(a,t.output[0]*t.output[1]).map(function(e){return n.splitArray(e,t.output[0])}):void 0}constructor(e,t){super(e,t),this.transferValues=null,this.formatValues=null,this.TextureConstructor=null,this.renderOutput=null,this.renderRawOutput=null,this.texSize=null,this.translatedSource=null,this.compiledFragmentShader=null,this.compiledVertexShader=null,this.switchingKernels=null,this._textureSwitched=null,this._mappedTextureSwitched=null}checkTextureSize(){const{features:e}=this.constructor;if(this.texSize[0]>e.maxTextureSize||this.texSize[1]>e.maxTextureSize)throw new Error(`Texture size [${this.texSize[0]},${this.texSize[1]}] generated by kernel is larger than supported size [${e.maxTextureSize},${e.maxTextureSize}]`)}translateSource(){throw new Error(`"translateSource" not defined on ${this.constructor.name}`)}pickRenderStrategy(e){if(this.graphical)return this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=e=>e,this.TextureConstructor=K,null;if("unsigned"===this.precision)if(this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=this.readPackedPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=U,null):this.output[1]>0?(this.TextureConstructor=B,null):(this.TextureConstructor=V,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else switch(null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.renderOutput=this.renderValues,this.output[2]>0?(this.TextureConstructor=U,this.formatValues=n.erect3DPackedFloat,null):this.output[1]>0?(this.TextureConstructor=B,this.formatValues=n.erect2DPackedFloat,null):(this.TextureConstructor=V,this.formatValues=n.erectPackedFloat,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else{if("single"!==this.precision)throw new Error(`unhandled precision of "${this.precision}"`);if(this.renderRawOutput=this.readFloatPixelsToFloat32Array,this.transferValues=this.readFloatPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.optimizeFloatMemory?this.output[2]>0?(this.TextureConstructor=z,null):this.output[1]>0?(this.TextureConstructor=N,null):(this.TextureConstructor=O,null):this.output[2]>0?(this.TextureConstructor=M,null):this.output[1]>0?(this.TextureConstructor=R,null):(this.TextureConstructor=G,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,null):this.output[1]>0?(this.TextureConstructor=o,null):(this.TextureConstructor=s,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,null):this.output[1]>0?(this.TextureConstructor=h,null):(this.TextureConstructor=l,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=D,null):this.output[1]>0?(this.TextureConstructor=d,null):(this.TextureConstructor=p,null)}if(this.renderOutput=this.renderValues,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.optimizeFloatMemory)switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=z,this.formatValues=n.erectMemoryOptimized3DFloat,null):this.output[1]>0?(this.TextureConstructor=N,this.formatValues=n.erectMemoryOptimized2DFloat,null):(this.TextureConstructor=O,this.formatValues=n.erectMemoryOptimizedFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=n.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=n.erect2DArray2,null):(this.TextureConstructor=s,this.formatValues=n.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=n.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=n.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=n.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=D,this.formatValues=n.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=n.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=n.erectArray4,null)}else switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=M,this.formatValues=n.erect3DFloat,null):this.output[1]>0?(this.TextureConstructor=R,this.formatValues=n.erect2DFloat,null):(this.TextureConstructor=G,this.formatValues=n.erectFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=n.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=n.erect2DArray2,null):(this.TextureConstructor=s,this.formatValues=n.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=n.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=n.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=n.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=D,this.formatValues=n.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=n.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=n.erectArray4,null)}}throw new Error(`unhandled return type "${this.returnType}"`)}getKernelString(){throw new Error("abstract method call")}getMainResultTexture(){switch(this.returnType){case"LiteralInteger":case"Float":case"Integer":case"Number":return this.getMainResultNumberTexture();case"Array(2)":return this.getMainResultArray2Texture();case"Array(3)":return this.getMainResultArray3Texture();case"Array(4)":return this.getMainResultArray4Texture();default:throw new Error(`unhandled returnType type ${this.returnType}`)}}getMainResultKernelNumberTexture(){throw new Error("abstract method call")}getMainResultSubKernelNumberTexture(){throw new Error("abstract method call")}getMainResultKernelArray2Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray2Texture(){throw new Error("abstract method call")}getMainResultKernelArray3Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray3Texture(){throw new Error("abstract method call")}getMainResultKernelArray4Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray4Texture(){throw new Error("abstract method call")}getMainResultGraphical(){throw new Error("abstract method call")}getMainResultMemoryOptimizedFloats(){throw new Error("abstract method call")}getMainResultPackedPixels(){throw new Error("abstract method call")}getMainResultString(){return this.graphical?this.getMainResultGraphical():"single"===this.precision?this.optimizeFloatMemory?this.getMainResultMemoryOptimizedFloats():this.getMainResultTexture():this.getMainResultPackedPixels()}getMainResultNumberTexture(){return n.linesToString(this.getMainResultKernelNumberTexture())+n.linesToString(this.getMainResultSubKernelNumberTexture())}getMainResultArray2Texture(){return n.linesToString(this.getMainResultKernelArray2Texture())+n.linesToString(this.getMainResultSubKernelArray2Texture())}getMainResultArray3Texture(){return n.linesToString(this.getMainResultKernelArray3Texture())+n.linesToString(this.getMainResultSubKernelArray3Texture())}getMainResultArray4Texture(){return n.linesToString(this.getMainResultKernelArray4Texture())+n.linesToString(this.getMainResultSubKernelArray4Texture())}getFloatTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} float;\n`}getIntTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic,!0)} int;\n`}getSampler2DTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2D;\n`}getSampler2DArrayTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2DArray;\n`}renderTexture(){return this.immutable?this.texture.clone():this.texture}readPackedPixelsToUint8Array(){if("unsigned"!==this.precision)throw new Error('Requires this.precision to be "unsigned"');const{texSize:e,context:t}=this,r=new Uint8Array(e[0]*e[1]*4);return t.readPixels(0,0,e[0],e[1],t.RGBA,t.UNSIGNED_BYTE,r),r}readPackedPixelsToFloat32Array(){return new Float32Array(this.readPackedPixelsToUint8Array().buffer)}readFloatPixelsToFloat32Array(){if("single"!==this.precision)throw new Error('Requires this.precision to be "single"');const{texSize:e,context:t}=this,r=e[0],n=e[1],s=new Float32Array(r*n*4);return t.readPixels(0,0,r,n,t.RGBA,t.FLOAT,s),s}getPixels(e){const{context:t,output:r}=this,[s,i]=r,a=new Uint8Array(s*i*4);t.readPixels(0,0,s,i,t.RGBA,t.UNSIGNED_BYTE,a);const o=new Uint8ClampedArray((e?a:n.flipPixels(a,s,i)).buffer);return this.asyncMode?Promise.resolve(o):o}renderKernelsToArrays(){const e={result:this.renderOutput()};for(let t=0;t0){for(let e=0;e0){const{mappedTextures:r}=this;for(let n=0;n{const{utils:r}=i(),{FunctionNode:n}=l(),s={"<":"ceil",">=":"ceil",">":"floor","<=":"floor"};function a(e){if(!e||"object"!=typeof e)return!0;if(Array.isArray(e))return e.every(a);if("UpdateExpression"===e.type||"AssignmentExpression"===e.type||"SequenceExpression"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&!a(e[t]))return!1;return!0}function o(e){let t=!1;function r(e){if(!e||"object"!=typeof e||t)return!1;if(Array.isArray(e))return e.some(r);if("MemberExpression"===e.type&&e.computed)return!0;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t]))return!0;return!1}return function e(n){if(n&&"object"==typeof n&&!t)if(Array.isArray(n))n.forEach(e);else if("MemberExpression"===n.type&&n.computed&&r(n.property))t=!0;else for(const t in n)"loc"!==t&&"range"!==t&&"parent"!==t&&e(n[t])}(e),t}function u(e,t){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>u(e,t));if("CallExpression"===e.type&&"Identifier"===e.callee.type&&e.callee.name===t)return!0;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&u(e[r],t))return!0;return!1}function h(e){let t=!1;return function e(r){if(r&&"object"==typeof r&&!t)if(Array.isArray(r))r.forEach(e);else if("CallExpression"===r.type&&"Identifier"===r.callee.type&&r.arguments.some(e=>u(e,r.callee.name)))t=!0;else for(const t in r)"loc"!==t&&"range"!==t&&"parent"!==t&&e(r[t])}(e),t}function c(e){const t="ExpressionStatement"===e.type&&"AssignmentExpression"===e.expression.type?e.expression:null;return function e(r){if(!r||"object"!=typeof r)return!0;if(Array.isArray(r))return r.every(e);if("string"==typeof r.type){if("UpdateExpression"===r.type||"SequenceExpression"===r.type)return!1;if("AssignmentExpression"===r.type&&r!==t)return!1}for(const t in r)if("loc"!==t&&"range"!==t&&"parent"!==t&&!e(r[t]))return!1;return!0}(e)}const p={"Matrix(2)":2,"Matrix(3)":3,"Matrix(4)":4},d={Array:"sampler2D","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4","Matrix(2)":"mat2","Matrix(3)":"mat3","Matrix(4)":"mat4",Array2D:"sampler2D",Array3D:"sampler2D",Boolean:"bool",Float:"float",Input:"sampler2D",Integer:"int",Number:"float",LiteralInteger:"float",NumberTexture:"sampler2D",MemoryOptimizedNumberTexture:"sampler2D","ArrayTexture(1)":"sampler2D","ArrayTexture(2)":"sampler2D","ArrayTexture(3)":"sampler2D","ArrayTexture(4)":"sampler2D",HTMLVideo:"sampler2D",HTMLCanvas:"sampler2D",OffscreenCanvas:"sampler2D",HTMLImage:"sampler2D",ImageBitmap:"sampler2D",ImageData:"sampler2D",HTMLImageArray:"sampler2DArray"},f={"===":"==","!==":"!="};t.exports={WebGLFunctionNode:class extends n{constructor(e,t){super(e,t),t&&t.hasOwnProperty("fixIntegerDivisionAccuracy")&&(this.fixIntegerDivisionAccuracy=t.fixIntegerDivisionAccuracy)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const r=this.getType(e.consequent),n=this.getType(e.alternate);return null===r&&null===n?(t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t):(t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t)}astFunction(e,t){if(this.isRootKernel)t.push("void");else{this.returnType||this.findLastReturn()&&(this.returnType=this.getType(e.body),"LiteralInteger"===this.returnType&&(this.returnType="Number"));const{returnType:r}=this;if(r){const e=d[r];if(!e)throw new Error(`unknown type ${r}`);t.push(e)}else t.push("void")}if(t.push(" "),t.push(this.name),t.push("("),!this.isRootKernel)for(let n=0;n0&&t.push(", ");let i=this.argumentTypes[this.argumentNames.indexOf(s)];if(!i)throw this.astErrorOutput(`Unknown argument ${s} type`,e);"LiteralInteger"===i&&(this.argumentTypes[n]=i="Number");const a=d[i];if(!a)throw this.astErrorOutput("Unexpected expression",e);const o=r.sanitizeName(s);"sampler2D"===a||"sampler2DArray"===a?t.push(`${a} user_${o},ivec2 user_${o}Size,ivec3 user_${o}Dim`):t.push(`${a} user_${o}`)}if(t.push(") {\n"),this.isRootKernel){const e=this.getAssignedArguments();for(let n=0;n>":"bitwiseSignedRightShift",">>>":"bitwiseZeroFillRightShift"}[e.operator];if(!r)return null;switch(t.push(r),t.push("("),this.getType(e.left)){case"Number":case"Float":this.castValueToInteger(e.left,t);break;case"LiteralInteger":this.castLiteralToInteger(e.left,t);break;default:this.astGeneric(e.left,t)}switch(t.push(","),this.getType(e.right)){case"Number":case"Float":this.castValueToInteger(e.right,t);break;case"LiteralInteger":this.castLiteralToInteger(e.right,t);break;default:this.astGeneric(e.right,t)}return t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){const r={"~":"bitwiseNot"}[e.operator];if(!r)return null;switch(t.push(r),t.push("("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("int("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("float("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const n=this.getType(e),s=r.sanitizeName(e.name);if("Infinity"===e.name)t.push("3.402823466e+38");else if("Boolean"===n)if(this.argumentNames.indexOf(s)>-1){const r=this.markupUserName(e.name);t.push(r.startsWith("cellShadow_")?r:`bool(${r})`)}else t.push(`user_${s}`);else t.push(this.markupUserName(e.name));return t}markupUserName(e){const t=r.sanitizeName(e);if(this.isRootKernel&&this.getAssignedArguments().has(e)){const r=this.argumentNames.indexOf(e),n=-1===r?null:d[this.argumentTypes[r]];if("float"===n||"int"===n||"bool"===n)return`cellShadow_user_${t}`}return`user_${t}`}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const r=[],n=[],s=[],i=[];let a=null;if(e.init)if("VariableDeclaration"!==e.init.type)a=!1,this.astGeneric(e.init,r),r.push(";");else{const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,r);for(let e=0;e{const t=this.getDeclaration(e);return null!==t&&r.has(t)},a=e=>{if(e&&"object"==typeof e&&!s)if(Array.isArray(e))for(const t of e)a(t);else if("ForStatement"!==e.type||!e.init||"VariableDeclaration"!==e.init.type||!e.init.declarations.some(e=>e.id&&"Identifier"===e.id.type&&n.has(e.id.name)))if("AssignmentExpression"===e.type&&"Identifier"===e.left.type&&i(e.left))s=!0;else if("UpdateExpression"===e.type&&"Identifier"===e.argument.type&&i(e.argument))s=!0;else for(const t in e){if("loc"===t||"range"===t||"parent"===t)continue;const r=e[t];r&&"object"==typeof r&&a(r)}};return a(e.body),!s&&e.test&&a(e.test),s}emitForParts(e,t){const{initArr:r,testArr:n,updateArr:s,bodyArr:i,isSafe:a}=e;if(a){const e=r.join(""),a=";"!==e[e.length-1];t.push(`for (${e}${a?";":""}${n.join("")};${s.join("")}){\n`),t.push(i.join("")),t.push("}\n")}else{const e=this.getInternalVariableName("safeI");r.length>0&&t.push(r.join(""),"\n"),t.push(`for (int ${e}=0;${e}0&&t.push(`if (!${n.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=this.getInternalVariableName("safeI");return t.push(`for (int ${r}=0;${r}0){if (!`),this.astGeneric(e.test,t),t.push(") break;}\n"),this.astGeneric(e.body,t),t.push("}\n"),t}astAssignmentExpression(e,t){const r=this.isState("assignment-as-statement");if(r?this.popState("assignment-as-statement"):t.push("("),"%="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("mod("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else if("**="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("pow("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else{const r=this.getType(e.left),n=this.getType(e.right);this.astGeneric(e.left,t),t.push(e.operator),"Integer"!==r&&"Integer"===n?(t.push("float("),this.astGeneric(e.right,t),t.push(")")):"Integer"===r&&"LiteralInteger"===n?this.castLiteralToInteger(e.right,t):this.astGeneric(e.right,t)}return r||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let r=0;rnull!==e&&(o(e)||h(e))))return null;const i=e=>JSON.parse(JSON.stringify(e)),a=e=>({type:"IfStatement",test:{type:"UnaryExpression",operator:"!",prefix:!0,argument:e},consequent:{type:"BlockStatement",body:[{type:"BreakStatement",label:null}]},alternate:null}),u=e=>"VariableDeclaration"===e.type?e:{type:"ExpressionStatement",expression:e},l="BlockStatement"===e.body.type?e.body.body.slice():[e.body],c=(e,t)=>{const r=e=>{if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(r);switch(e.type){case"ContinueStatement":return{type:"BlockStatement",body:[...t(),e]};case"ForStatement":case"WhileStatement":case"DoWhileStatement":default:return e;case"IfStatement":return{...e,consequent:r(e.consequent),alternate:r(e.alternate)};case"BlockStatement":return{...e,body:e.body.map(r)};case"SwitchStatement":return{...e,cases:e.cases.map(e=>({...e,consequent:e.consequent.map(r)}))}}};return e.map(r)},p=[];"DoWhileStatement"===t?(p.push(...n?c(l,()=>[a(i(n))]):l),n&&p.push(a(n))):(n&&p.push(a(n)),p.push(...s?c(l,()=>[u(i(s))]):l),s&&p.push(u(s)));const d={type:"BlockStatement",body:[...r?[u(r)]:[],{type:"WhileStatement",test:{type:"Literal",value:!0,raw:"true"},body:{type:"BlockStatement",body:p}}]};return this.stampSyntheticNodes(d),d}stampSyntheticNodes(e){let t=this.syntheticNodeId||1073741824;const r=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(r);else{"string"==typeof e.type&&void 0===e.start&&(e.start=t,e.end=t+1,t+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t])}};r(e),this.syntheticNodeId=t}linearizeStatement(e){const t=[];let r=!1,n=this.linearTempId||0;const s=e=>({type:"Identifier",name:e}),i=(e,t,r)=>({type:"VariableDeclaration",kind:e,declarations:[{type:"VariableDeclarator",id:s(t),init:r}]}),o=(e,t)=>{const r="hoistSeq"+n++;return e.push(i("const",r,t)),s(r)},l=e=>!a(e),h=(e,t)=>{if(r||!e||"object"!=typeof e)return e;switch(e.type){case"Identifier":case"Literal":case"ThisExpression":return e;case"MemberExpression":{const r=h(e.object,t),n=e.computed?h(e.property,t):e.property;return{...e,object:r,property:n}}case"CallExpression":{const r=e.arguments.map(e=>h(e,t));if("Identifier"===e.callee.type)for(let n=0;nh(e,t))};case"UpdateExpression":{if("Identifier"!==e.argument.type)return r=!0,e;if(e.prefix)return t.push({type:"ExpressionStatement",expression:e}),o(t,e.argument);const n=o(t,e.argument);return t.push({type:"ExpressionStatement",expression:e}),n}case"AssignmentExpression":{if("Identifier"!==e.left.type)return r=!0,e;const n=h(e.right,t);return t.push({type:"ExpressionStatement",expression:{...e,right:n}}),o(t,e.left)}case"SequenceExpression":for(let r=0;r({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:s(e),right:t}});return o.push(d(a,c)),u.push(d(a,p)),t.push({type:"IfStatement",test:r,consequent:{type:"BlockStatement",body:o},alternate:{type:"BlockStatement",body:u}}),s(a)}case"LogicalExpression":{if(!l(e.right))return{...e,left:h(e.left,t)};const r=h(e.left,t),a="hoistSeq"+n++;t.push(i("let",a,r));const o=[],u=h(e.right,o);return o.push({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:s(a),right:u}}),t.push({type:"IfStatement",test:"&&"===e.operator?s(a):{type:"UnaryExpression",operator:"!",prefix:!0,argument:s(a)},consequent:{type:"BlockStatement",body:o},alternate:null}),s(a)}default:return r=!0,e}};switch(e.type){case"ExpressionStatement":{const r=e.expression;if("AssignmentExpression"===r.type&&"Identifier"===r.left.type){const e=h(r.right,t);t.push({type:"ExpressionStatement",expression:{...r,right:e}})}else{const e=h(r,t);"UpdateExpression"!==e.type&&"AssignmentExpression"!==e.type||t.push({type:"ExpressionStatement",expression:e})}break}case"VariableDeclaration":for(let r=0;r{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(p);else{"string"==typeof e.type&&void 0===e.start&&(e.start=c,e.end=c+1,c+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&p(e[t])}};return p(t),this.syntheticNodeId=c,t}astStatementWithHoisting(e,t){switch(e.type){case"ExpressionStatement":case"VariableDeclaration":case"ReturnStatement":{if(!c(e))return this.astGeneric(e,t);const r=this.hoistedIndexReads,n=this.hoistedIndexReads=[],s=[];return this.astGeneric(e,s),this.hoistedIndexReads=r,t.push(...n,...s),t}default:return this.astGeneric(e,t)}}astVariableDeclaration(e,t){const n=e.declarations;if(!n||!n[0]||!n[0].init)throw this.astErrorOutput("Unexpected expression",e);const s=[];let i=null;const a=[];let o=[];for(let t=0;t0&&a.push(o.join(",")),s.push(a.join(";")),t.push(s.join("")),t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchCaseConsequent(e,t){const r=[];for(let t=0;t{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&t(e[r]))return!0;return!1};if(t(r[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",r[e])}for(let e=0;er+1){u=!0,this.astSwitchCaseConsequent(n[r].consequent,o);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(n[r].consequent,t),t.push("\n}")}return u&&(t.push(" else {"),t.push(o.join("")),t.push("}")),t}astThisExpression(e,t){return t.push("this"),t}astMemberExpression(e,t){const{property:n,name:s,signature:i,origin:a,type:o,xProperty:u,yProperty:l,zProperty:h}=this.getMemberExpressionDetails(e);switch(i){case"value.thread.value":case"this.thread.value":if("x"!==s&&"y"!==s&&"z"!==s)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`threadId.${s}`),t;case"this.output.value":if(this.dynamicOutput)switch(s){case"x":this.isState("casting-to-float")?t.push("float(uOutputDim.x)"):t.push("uOutputDim.x");break;case"y":this.isState("casting-to-float")?t.push("float(uOutputDim.y)"):t.push("uOutputDim.y");break;case"z":this.isState("casting-to-float")?t.push("float(uOutputDim.z)"):t.push("uOutputDim.z");break;default:throw this.astErrorOutput("Unexpected expression",e)}else switch(s){case"x":this.isState("casting-to-integer")?t.push(this.output[0]):t.push(this.output[0],".0");break;case"y":this.isState("casting-to-integer")?t.push(this.output[1]):t.push(this.output[1],".0");break;case"z":this.isState("casting-to-integer")?t.push(this.output[2]):t.push(this.output[2],".0");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===a)return t.push(Math[s]),t;const i=r.sanitizeName(s);switch(n){case"r":return t.push(`user_${i}.r`),t;case"g":return t.push(`user_${i}.g`),t;case"b":return t.push(`user_${i}.b`),t;case"a":return t.push(`user_${i}.a`),t}break;case"this.constants.value":if(void 0===u)switch(o){case"Array(2)":case"Array(3)":case"Array(4)":return t.push(`constants_${r.sanitizeName(s)}`),t}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":break;case"fn()[]":return this.astCallExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(n)),t.push("]"),t;case"fn()[][]":{const r=e.object.property,n=e.property,s=p[this.getType(e.object.object)],i=e=>"LiteralInteger"===this.getType(e);return!s||i(r)&&i(n)?(this.astCallExpression(e.object.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t.push("["),t.push(this.memberExpressionPropertyMarkup(n)),t.push("]"),t):(t.push(`getMatrix${s}(`),this.astCallExpression(e.object.object,t),t.push(", "),t.push(this.memberExpressionPropertyMarkup(r)),t.push(", "),t.push(this.memberExpressionPropertyMarkup(n)),t.push(")"),t)}case"[][]":return this.astArrayExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(n)),t.push("]"),t;default:throw this.astErrorOutput("Unexpected expression",e)}if(!1===e.computed)switch(o){case"Number":case"Integer":case"Float":case"Boolean":return t.push(`${a}_${r.sanitizeName(s)}`),t}const c=`${a}_${r.sanitizeName(s)}`;switch(o){case"Array(2)":case"Array(3)":case"Array(4)":this.astGeneric(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(u)),t.push("]");break;case"HTMLImageArray":t.push(`getImage3D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(1)":t.push(`getFloatFromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(2)":case"Array2D(2)":case"Array3D(2)":t.push(`getMemoryOptimizedVec2(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(2)":t.push(`getVec2FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(3)":case"Array2D(3)":case"Array3D(3)":t.push(`getMemoryOptimizedVec3(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(3)":t.push(`getVec3FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(4)":case"Array2D(4)":case"Array3D(4)":t.push(`getMemoryOptimizedVec4(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(4)":case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":t.push(`getVec4FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"NumberTexture":case"Array":case"Array2D":case"Array3D":case"Array4D":case"Input":case"Number":case"Float":case"Integer":if("single"===this.precision)t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");else{const e="user"===a?this.lookupFunctionArgumentBitRatio(this.name,s):this.constantBitRatios[s];switch(e){case 1:t.push(`get8(${c}, ${c}Size, ${c}Dim, `);break;case 2:t.push(`get16(${c}, ${c}Size, ${c}Dim, `);break;case 4:case 0:t.push(`get32(${c}, ${c}Size, ${c}Dim, `);break;default:throw new Error(`unhandled bit ratio of ${e}`)}this.memberExpressionXYZ(u,l,h,t),t.push(")")}break;case"MemoryOptimizedNumberTexture":t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`${c}[${this.memberExpressionPropertyMarkup(l)}]`),l&&t.push(`[${this.memberExpressionPropertyMarkup(u)}]`);break;default:throw new Error(`unhandled member expression "${o}"`)}return t}astCallExpression(e,t){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);let n=null;const s=this.isAstMathFunction(e);if(n=s||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!n)throw this.astErrorOutput("Unhandled function, couldn't find name",e);switch(n){case"pow":n="_pow";break;case"round":n="_round"}if(this.calledFunctions.indexOf(n)<0&&this.calledFunctions.push(n),"random"===n&&this.plugins&&this.plugins.length>0)for(let e=0;e0&&t.push(", "),"Integer"===s)this.castValueToFloat(n,t);else this.astGeneric(n,t)}else{const s=this.lookupFunctionArgumentTypes(n)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(n,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("int("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("float("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.astGeneric(a,t);continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){if("Identifier"===a.type)t.push(`user_${r.sanitizeName(a.name)}`);else{if("ArrayExpression"!==a.type&&"MemberExpression"!==a.type&&"CallExpression"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.astGeneric(a,t)}continue}break;case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLImageArray":case"HTMLVideo":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":case"Array":case"Input":if(o===u){if("Identifier"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.triggerImplyArgumentBitRatio(this.name,a.name,n,i);const s=r.sanitizeName(a.name);t.push(`user_${s},user_${s}Size,user_${s}Dim`);continue}}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),t}astArrayExpression(e,t){const r=this.getType(e),n=e.elements.length;switch(r){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`mat${n}(`);break;default:t.push(`vec${n}(`)}for(let r=0;r0&&t.push(", ");const n=e.elements[r];this.astGeneric(n,t)}return t.push(")"),t}memberExpressionXYZ(e,t,r,n){return r?n.push(this.memberExpressionPropertyMarkup(r),", "):n.push("0, "),t?n.push(this.memberExpressionPropertyMarkup(t),", "):n.push("0, "),n.push(this.memberExpressionPropertyMarkup(e)),n}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.astGeneric(e,t)}const n=t.join("");if(this.hoistedIndexReads&&/\b\w+\((user_|constants_)\w+, \1\w+Size/.test(n)){const e=`hoisted_${this.hoistedIndexReads.length}_${r.sanitizeName(this.name)}`,t=n.startsWith("int(");return this.hoistedIndexReads.push(`${t?"int":"float"} ${e}=${n};\n`),e}return n}}}}),R=e((e,t)=>{t.exports={name:"math-random-uniformly-distributed",onBeforeRun:e=>{if(null===e.randomSeed||void 0===e.randomSeed)return e.setUniform1f("randomSeed1",Math.random()),void e.setUniform1f("randomSeed2",Math.random());e._mathRandomGenerator&&e._mathRandomGeneratorSeed===e.randomSeed||(e._mathRandomGenerator=function(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(e.randomSeed),e._mathRandomGeneratorSeed=e.randomSeed),e.setUniform1f("randomSeed1",e._mathRandomGenerator()),e.setUniform1f("randomSeed2",e._mathRandomGenerator())},functionMatch:"Math.random()",functionReplace:"nrand(vTexCoord)",functionReturnType:"Number",source:"// https://www.shadertoy.com/view/4t2SDh\n//note: uniformly distributed, normalized rand, [0,1]\nhighp float randomSeedShift = 1.0;\nhighp float slide = 1.0;\nuniform highp float randomSeed1;\nuniform highp float randomSeed2;\n\nhighp float nrand(highp vec2 n) {\n highp float result = fract(sin(dot((n.xy + 1.0) * vec2(randomSeed1 * slide, randomSeed2 * randomSeedShift), vec2(12.9898, 78.233))) * 43758.5453);\n randomSeedShift = result;\n if (randomSeedShift > 0.5) {\n slide += 0.00009; \n } else {\n slide += 0.0009;\n }\n return result;\n}"}}),M=e((e,t)=>{t.exports={fragmentShader:`__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nvarying vec2 vTexCoord;\n\nfloat acosh(float x) {\n return log(x + sqrt(x * x - 1.0));\n}\n\nfloat sinh(float x) {\n return (pow(${Math.E}, x) - pow(${Math.E}, -x)) / 2.0;\n}\n\nfloat asinh(float x) {\n return log(x + sqrt(x * x + 1.0));\n}\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat atanh(float x) {\n x = (x + 1.0) / (x - 1.0);\n if (x < 0.0) {\n return 0.5 * log(-x);\n }\n return 0.5 * log(x);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat cosh(float x) {\n return (pow(${Math.E}, x) + pow(${Math.E}, -x)) / 2.0; \n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat tanh(float x) {\n float e = exp(2.0 * x);\n return (e - 1.0) / (e + 1.0);\n}\n\nfloat trunc(float x) {\n if (x >= 0.0) {\n return floor(x); \n } else {\n return ceil(x);\n }\n}\n\nvec4 _round(vec4 x) {\n return floor(x + 0.5);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x / y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(_round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(_round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;\n if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;\n return 0.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n if (channel == 0) return texel.r * 255.0;\n if (channel == 1) return texel.g * 255.0;\n if (channel == 2) return texel.b * 255.0;\n if (channel == 3) return texel.a * 255.0;\n return 0.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return texel.r;\n if (channel == 1) return texel.g;\n if (channel == 2) return texel.b;\n if (channel == 3) return texel.a;\n return 0.0;\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture2D(tex, st / vec2(texSize));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n \n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nvoid color(sampler2D image) {\n actualColor = texture2D(image, vTexCoord);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),O=e((e,t)=>{t.exports={vertexShader:"__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nattribute vec2 aPos;\nattribute vec2 aTexCoord;\n\nvarying vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),N=e((e,t)=>{function r(e,t={}){const{contextName:r="gl",throwGetError:a,useTrackablePrimitives:o,recording:u=[],variables:l={},onReadPixels:h,onUnrecognizedArgumentLookup:c}=t,p=new Proxy(e,{get:function(t,p){switch(p){case"addComment":return A;case"checkThrowError":return w;case"getReadPixelsVariableName":return m;case"insertVariable":return b;case"reset":return x;case"setIndent":return T;case"toString":return y;case"getContextVariableName":return E}return"function"==typeof e[p]?function(){switch(p){case"getError":return a?u.push(`${g}if (${r}.getError() !== ${r}.NONE) throw new Error('error');`):u.push(`${g}${r}.getError();`),e.getError();case"getExtension":{const t=`${r}Variables${d.length}`;u.push(`${g}const ${t} = ${r}.getExtension('${arguments[0]}');`);const s=e.getExtension(arguments[0]);if(s&&"object"==typeof s){const e=n(s,{getEntity:v,useTrackablePrimitives:o,recording:u,contextName:t,contextVariables:d,variables:l,indent:g,onUnrecognizedArgumentLookup:c});return d.push(e),e}return d.push(null),s}case"readPixels":const t=d.indexOf(arguments[6]);let i;if(-1===t){const e=function(e){if(l)for(const t in l)if(l[t]===e)return t;return null}(arguments[6]);e?(i=e,u.push(`${g}${e}`)):(i=`${r}Variable${d.length}`,d.push(arguments[6]),u.push(`${g}const ${i} = new ${arguments[6].constructor.name}(${arguments[6].length});`))}else i=`${r}Variable${t}`;m=i;const p=[arguments[0],arguments[1],arguments[2],arguments[3],v(arguments[4]),v(arguments[5]),i];return u.push(`${g}${r}.readPixels(${p.join(", ")});`),h&&h(i,p),e.readPixels.apply(e,arguments);case"drawBuffers":return u.push(`${g}${r}.drawBuffers([${s(arguments[0],{contextName:r,contextVariables:d,getEntity:v,addVariable:S,variables:l,onUnrecognizedArgumentLookup:c})}]);`),e.drawBuffers(arguments[0])}let t=e[p].apply(e,arguments);switch(typeof t){case"undefined":return void u.push(`${g}${_(p,arguments)};`);case"number":case"boolean":if(o&&-1===d.indexOf(i(t))){u.push(`${g}const ${r}Variable${d.length} = ${_(p,arguments)};`),d.push(t=i(t));break}default:null===t?u.push(`${_(p,arguments)};`):u.push(`${g}const ${r}Variable${d.length} = ${_(p,arguments)};`),d.push(t)}return t}:(f[e[p]]=p,e[p])}}),d=[],f={};let m,g="";return p;function y(){return u.join("\n")}function x(){for(;u.length>0;)u.pop()}function b(e,t){l[e]=t}function v(e){const t=f[e];return t?r+"."+t:e}function T(e){g=" ".repeat(e)}function S(e,t){const n=`${r}Variable${d.length}`;return u.push(`${g}const ${n} = ${t};`),d.push(e),n}function A(e){u.push(`${g}// ${e}`)}function w(){u.push(`${g}(() => {\n${g}const error = ${r}.getError();\n${g}if (error !== ${r}.NONE) {\n${g} const names = Object.getOwnPropertyNames(gl);\n${g} for (let i = 0; i < names.length; i++) {\n${g} const name = names[i];\n${g} if (${r}[name] === error) {\n${g} throw new Error('${r} threw ' + name);\n${g} }\n${g} }\n${g}}\n${g}})();`)}function _(e,t){return`${r}.${e}(${s(t,{contextName:r,contextVariables:d,getEntity:v,addVariable:S,variables:l,onUnrecognizedArgumentLookup:c})})`}function E(e){const t=d.indexOf(e);return-1!==t?`${r}Variable${t}`:null}}function n(e,t){const r=new Proxy(e,{get:function(t,r){return"function"==typeof t[r]?function(){if("drawBuffersWEBGL"===r)return h.push(`${p}${a}.drawBuffersWEBGL([${s(arguments[0],{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})}]);`),e.drawBuffersWEBGL(arguments[0]);let t=e[r].apply(e,arguments);switch(typeof t){case"undefined":return void h.push(`${p}${m(r,arguments)};`);case"number":case"boolean":l&&-1===o.indexOf(i(t))?(h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t=i(t))):(h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t));break;default:null===t?h.push(`${m(r,arguments)};`):h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t)}return t}:(n[e[r]]=r,e[r])}}),n={},{contextName:a,contextVariables:o,getEntity:u,useTrackablePrimitives:l,recording:h,variables:c,indent:p,onUnrecognizedArgumentLookup:d}=t;return r;function f(e){return n.hasOwnProperty(e)?`${a}.${n[e]}`:u(e)}function m(e,t){return`${a}.${e}(${s(t,{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})})`}function g(e,t){const r=`${a}Variable${o.length}`;return o.push(e),h.push(`${p}const ${r} = ${t};`),r}}function s(e,t){const{variables:r,onUnrecognizedArgumentLookup:n}=t;return Array.from(e).map(e=>{const s=function(e){if(r)for(const t in r)if(r.hasOwnProperty(t)&&r[t]===e)return t;return n?n(e):null}(e);return s||function(e,t){const{contextName:r,contextVariables:n,getEntity:s,addVariable:i,onUnrecognizedArgumentLookup:a}=t;if(void 0===e)return"undefined";if(null===e)return"null";const o=n.indexOf(e);if(o>-1)return`${r}Variable${o}`;switch(e.constructor.name){case"String":const t=/\n/.test(e),r=/'/.test(e),n=/"/.test(e);return t?"`"+e+"`":r&&!n?'"'+e+'"':"'"+e+"'";case"Number":case"Boolean":return s(e);case"Array":return i(e,`new ${e.constructor.name}([${Array.from(e).join(",")}])`);case"Float32Array":case"Uint8Array":case"Uint16Array":case"Int32Array":return i(e,`new ${e.constructor.name}(${JSON.stringify(Array.from(e))})`);default:if(a){const t=a(e);if(t)return t}throw new Error(`unrecognized argument type ${e.constructor.name}`)}}(e,t)}).join(", ")}function i(e){return new e.constructor(e)}void 0!==t&&(t.exports={glWiretap:r,glExtensionWiretap:n}),"undefined"!=typeof window&&(r.glExtensionWiretap=n,window.glWiretap=r)}),z=e((e,t)=>{const{glWiretap:r}=N(),{utils:n}=i();function s(e){let t=e.toString().replace(/^function /,"");const r=t.indexOf("=>");if(-1!==r&&!/[{]|\bfunction\b/.test(t.slice(0,r))){const e=t.slice(0,r).trim(),n=t.slice(r+2).trim();t=n.startsWith("{")?`${e} ${n}`:`${e} { return ${n}; }`}return t.replace(/utils[.]/g,"/*utils.*/")}function a(e,t){const r="single"===t.precision?e:`new Float32Array(${e}.buffer)`;return t.output[2]?`renderOutput(${r}, ${t.output[0]}, ${t.output[1]}, ${t.output[2]})`:t.output[1]?`renderOutput(${r}, ${t.output[0]}, ${t.output[1]})`:`renderOutput(${r}, ${t.output[0]})`}function o(e,t){const r=e.toArray.toString(),s=!/^function/.test(r);return`() => {\n function framebuffer() { return getReadFramebuffer(); };\n ${n.flattenFunctionToString(`${s?"function ":""}${r}`,{findDependency:(t,r)=>{if("utils"===t)return`const ${r} = ${n[r].toString()};`;if("this"===t)return"framebuffer"===r?"":`${s?"function ":""}${e[r].toString()}`;throw new Error("unhandled fromObject")},thisLookup:(r,n)=>{if("texture"===r)return t;if("context"===r)return n?null:"gl";if(e.hasOwnProperty(r))return JSON.stringify(e[r]);throw new Error(`unhandled thisLookup ${r}`)}})}\n return toArray();\n }`}function u(e,t,r,n,s){if(null===e)return null;if(null===t)return null;switch(typeof e){case"boolean":case"number":return null}if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement)for(let s=0;s{switch(typeof e){case"boolean":return new Boolean(e);case"number":return new Number(e);default:return e}}):null;const c=[],p=[],d=r(i.context,{useTrackablePrimitives:!0,onReadPixels:e=>{if(R.subKernels){if(f){const t=R.subKernels[m++].property;p.push(` result${isNaN(t)?"."+t:`[${t}]`} = ${a(e,R)};`)}else p.push(` const result = { result: ${a(e,R)} };`),f=!0;m===R.subKernels.length&&p.push(" return result;")}else e?p.push(` return ${a(e,R)};`):p.push(" return null;")},onUnrecognizedArgumentLookup:e=>{const t=u(e,R.kernelArguments,[],d,c);if(t)return t;const r=u(e,R.kernelConstants,S?Object.keys(S).map(e=>S[e]):[],d,c);return r||null}});let f=!1,m=0;const{source:g,canvas:y,output:x,pipeline:b,graphical:v,loopMaxIterations:T,constants:S,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:L,argumentTypes:F,constantTypes:$,kernelArguments:C,kernelConstants:D,tactic:G}=i,R=new e(g,{canvas:y,context:d,checkContext:!1,output:x,pipeline:b,graphical:v,loopMaxIterations:T,constants:S,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:L,argumentTypes:F,constantTypes:$,tactic:G});let M=[];if(d.setIndent(2),R.build.apply(R,t),M.push(d.toString()),d.reset(),R.kernelArguments.forEach((e,r)=>{switch(e.type){case"Integer":case"Boolean":case"Number":case"Float":case"Array":case"Array(2)":case"Array(3)":case"Array(4)":case"HTMLCanvas":case"HTMLImage":case"HTMLVideo":case"Input":d.insertVariable(`uploadValue_${e.name}`,e.uploadValue);break;case"HTMLImageArray":for(let n=0;ne.varName).join(", ")}) {`),d.setIndent(4),R.run.apply(R,t),R.renderKernels?R.renderKernels():R.renderOutput&&R.renderOutput(),M.push(" /** start setup uploads for kernel values **/"),R.kernelArguments.forEach(e=>{M.push(" "+e.getStringValueHandler().split("\n").join("\n "))}),M.push(" /** end setup uploads for kernel values **/"),M.push(d.toString()),R.renderOutput===R.renderTexture)if(d.reset(),R.renderKernels){const e=R.renderKernels(),t=d.getContextVariableName(R.texture.texture);M.push(` return {\n result: {\n texture: ${t},\n type: '${e.result.type}',\n toArray: ${o(e.result,t)}\n },`);const{subKernels:r,mappedTextures:n}=R;for(let t=0;t"utils"===e?`const ${t} = ${n[t].toString()};`:null,thisLookup:t=>{if("context"===t)return null;if(e.hasOwnProperty(t))return JSON.stringify(e[t]);throw new Error(`unhandled thisLookup ${t}`)}})}(R)),M.push(" innerKernel.getPixels = getPixels;")),M.push(" return innerKernel;");let O=[];return D.forEach(e=>{O.push(`${e.getStringValueHandler()}`)}),`function kernel(settings) {\n const { context, constants } = settings;\n ${O.join("")}\n ${l||""}\n${M.join("\n")}\n}`}}}),V=e((e,t)=>{t.exports={KernelValue:class{constructor(e,t){const{name:r,kernel:n,context:s,checkContext:i,onRequestContextHandle:a,onUpdateValueMismatch:o,origin:u,strictIntegers:l,type:h,tactic:c}=t;if(!r)throw new Error("name not set");if(!h)throw new Error("type not set");if(!u)throw new Error("origin not set");if("user"!==u&&"constants"!==u)throw new Error(`origin must be "user" or "constants" value is "${u}"`);if(!a)throw new Error("onRequestContextHandle is not set");this.name=r,this.origin=u,this.tactic=c,this.varName="constants"===u?`constants.${r}`:r,this.kernel=n,this.strictIntegers=l,this.type=e.type||h,this.size=e.size||null,this.index=null,this.context=s,this.checkContext=null==i||i,this.contextHandle=null,this.onRequestContextHandle=a,this.onUpdateValueMismatch=o,this.forceUploadEachRun=null}get id(){return`${this.origin}_${name}`}getSource(){throw new Error(`"getSource" not defined on ${this.constructor.name}`)}updateValue(e){throw new Error(`"updateValue" not defined on ${this.constructor.name}`)}}}}),B=e((e,t)=>{const{utils:r}=i(),{KernelValue:n}=V();t.exports={WebGLKernelValue:class extends n{constructor(e,t){super(e,t),this.dimensionsId=null,this.sizeId=null,this.initialValueConstructor=e.constructor,this.onRequestTexture=t.onRequestTexture,this.onRequestIndex=t.onRequestIndex,this.uploadValue=null,this.textureSize=null,this.bitRatio=null,this.prevArg=null}get id(){return`${this.origin}_${r.sanitizeName(this.name)}`}setup(){}rebind(){}getTransferArrayType(e){if(Array.isArray(e[0]))return this.getTransferArrayType(e[0]);switch(e.constructor){case Array:case Int32Array:case Int16Array:case Int8Array:return Float32Array;case Uint8ClampedArray:case Uint8Array:case Uint16Array:case Uint32Array:case Float32Array:case Float64Array:return e.constructor}return console.warn("Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros"),e.constructor}getStringValueHandler(){throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`)}getVariablePrecisionString(){return this.kernel.getVariablePrecisionString(this.textureSize||void 0,this.tactic||void 0)}destroy(){}}}}),U=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:n}=B();t.exports={WebGLKernelValueBoolean:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const bool ${this.id} = ${e};\n`:`uniform bool ${this.id};\n`}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),K=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:n}=B();t.exports={WebGLKernelValueFloat:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?Number.isInteger(e)?`const float ${this.id} = ${r.glslFloatLiteral(e)};\n`:`const float ${this.id} = ${e};\n`:`uniform float ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1f(this.id,this.uploadValue=e)}}}}),P=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:n}=B();t.exports={WebGLKernelValueInteger:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?`const int ${this.id} = ${parseInt(e)};\n`:`uniform int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),W=e((e,t)=>{const{WebGLKernelValue:r}=B(),{Input:s}=n();t.exports={WebGLKernelArray:class extends r{rebind(){if(!this.texture||void 0===this.contextHandle||null===this.contextHandle)return;const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D,this.texture)}checkSize(e,t){if(!this.kernel.validate)return;const{maxTextureSize:r}=this.kernel.constructor.features;if(e>r||t>r)throw e>t?new Error(`Argument texture width of ${e} larger than maximum size of ${r} for your GPU`):e{const{utils:r}=i(),{WebGLKernelArray:n}=W();function s(e){return{width:e.width>0?e.width:e.videoWidth,height:e.height>0?e.height:e.videoHeight}}t.exports={WebGLKernelValueHTMLImage:class extends n{constructor(e,t){super(e,t);const{width:r,height:n}=s(e);this.checkSize(r,n),this.dimensions=[r,n,1],this.textureSize=[r,n],this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue=e),this.kernel.setUniform1i(this.id,this.index)}},mediaSize:s}}),q=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueHTMLImage:n,mediaSize:s}=j();t.exports={WebGLKernelValueDynamicHTMLImage:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:r}=s(e);this.checkSize(t,r),this.dimensions=[t,r,1],this.textureSize=[t,r],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),X=e((e,t)=>{const{WebGLKernelValueHTMLImage:r}=j();t.exports={WebGLKernelValueHTMLVideo:class extends r{}}}),H=e((e,t)=>{const{WebGLKernelValueDynamicHTMLImage:r}=q();t.exports={WebGLKernelValueDynamicHTMLVideo:class extends r{}}}),Y=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueSingleInput:class extends n{constructor(e,t){super(e,t),this.bitRatio=4;let[n,s,i]=e.size;this.dimensions=new Int32Array([n||1,s||1,i||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}.value, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Z=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleInput:n}=Y();t.exports={WebGLKernelValueDynamicSingleInput:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,n,s]=e.size;this.dimensions=new Int32Array([t||1,n||1,s||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),J=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueUnsignedInput:class extends n{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e);const[n,s,i]=e.size;this.dimensions=new Int32Array([n||1,s||1,i||1]),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e.value),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return r.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}.value, preUploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(value.constructor);const{context:t}=this;r.flattenTo(e.value,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Q=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedInput:n}=J();t.exports={WebGLKernelValueDynamicUnsignedInput:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,n,s]=e.size;this.dimensions=new Int32Array([t||1,n||1,s||1]),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const i=this.getTransferArrayType(e.value);this.preUploadValue=new i(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ee=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W(),s="Source and destination textures are the same. Use immutable = true and manually cleanup kernel output texture memory with texture.delete()";t.exports={WebGLKernelValueMemoryOptimizedNumberTexture:class extends n{constructor(e,t){super(e,t);const[r,n]=e.size;this.checkSize(r,n),this.dimensions=e.dimensions,this.textureSize=e.size,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:r}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(s);if(t.mappedTextures){const{mappedTextures:r}=t;for(let t=0;t{const{utils:r}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:n}=ee();t.exports={WebGLKernelValueDynamicMemoryOptimizedNumberTexture:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),re=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W(),{sameError:s}=ee();t.exports={WebGLKernelValueNumberTexture:class extends n{constructor(e,t){super(e,t);const[r,n]=e.size;this.checkSize(r,n);const{size:s,dimensions:i}=e;this.bitRatio=this.getBitRatio(e),this.dimensions=i,this.textureSize=s,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:r}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(s);if(t.mappedTextures){const{mappedTextures:r}=t;for(let t=0;t{const{utils:r}=i(),{WebGLKernelValueNumberTexture:n}=re();t.exports={WebGLKernelValueDynamicNumberTexture:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),se=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueSingleArray:class extends n{constructor(e,t){super(e,t),this.bitRatio=4,this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ie=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray:n}=se();t.exports={WebGLKernelValueDynamicSingleArray:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ae=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueSingleArray1DI:class extends n{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],1,1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten2dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),oe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray1DI:n}=ae();t.exports={WebGLKernelValueDynamicSingleArray1DI:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ue=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueSingleArray2DI:class extends n{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten3dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),le=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray2DI:n}=ue();t.exports={WebGLKernelValueDynamicSingleArray2DI:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),he=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueSingleArray3DI:class extends n{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],t[3]]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten4dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ce=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray3DI:n}=he();t.exports={WebGLKernelValueDynamicSingleArray3DI:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),pe=e((e,t)=>{const{WebGLKernelValue:r}=B();t.exports={WebGLKernelValueArray2:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec2 ${this.id} = vec2(${e[0]},${e[1]});\n`:`uniform vec2 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform2fv(this.id,this.uploadValue=e)}}}}),de=e((e,t)=>{const{WebGLKernelValue:r}=B();t.exports={WebGLKernelValueArray3:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec3 ${this.id} = vec3(${e[0]},${e[1]},${e[2]});\n`:`uniform vec3 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform3fv(this.id,this.uploadValue=e)}}}}),fe=e((e,t)=>{const{WebGLKernelValue:r}=B();t.exports={WebGLKernelValueArray4:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec4 ${this.id} = vec4(${e[0]},${e[1]},${e[2]},${e[3]});\n`:`uniform vec4 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform4fv(this.id,this.uploadValue=e)}}}}),me=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGLKernelValueUnsignedArray:class extends n{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e),this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return r.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}, preUploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ge=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedArray:n}=me();t.exports={WebGLKernelValueDynamicUnsignedArray:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const t=this.getTransferArrayType(e);this.preUploadValue=new t(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ye=e((e,t)=>{const{WebGLKernelValueBoolean:r}=U(),{WebGLKernelValueFloat:n}=K(),{WebGLKernelValueInteger:s}=P(),{WebGLKernelValueHTMLImage:i}=j(),{WebGLKernelValueDynamicHTMLImage:a}=q(),{WebGLKernelValueHTMLVideo:o}=X(),{WebGLKernelValueDynamicHTMLVideo:u}=H(),{WebGLKernelValueSingleInput:l}=Y(),{WebGLKernelValueDynamicSingleInput:h}=Z(),{WebGLKernelValueUnsignedInput:c}=J(),{WebGLKernelValueDynamicUnsignedInput:p}=Q(),{WebGLKernelValueMemoryOptimizedNumberTexture:d}=ee(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:f}=te(),{WebGLKernelValueNumberTexture:m}=re(),{WebGLKernelValueDynamicNumberTexture:g}=ne(),{WebGLKernelValueSingleArray:y}=se(),{WebGLKernelValueDynamicSingleArray:x}=ie(),{WebGLKernelValueSingleArray1DI:b}=ae(),{WebGLKernelValueDynamicSingleArray1DI:v}=oe(),{WebGLKernelValueSingleArray2DI:T}=ue(),{WebGLKernelValueDynamicSingleArray2DI:S}=le(),{WebGLKernelValueSingleArray3DI:A}=he(),{WebGLKernelValueDynamicSingleArray3DI:w}=ce(),{WebGLKernelValueArray2:_}=pe(),{WebGLKernelValueArray3:E}=de(),{WebGLKernelValueArray4:I}=fe(),{WebGLKernelValueUnsignedArray:k}=me(),{WebGLKernelValueDynamicUnsignedArray:L}=ge(),F={unsigned:{dynamic:{Boolean:r,Integer:s,Float:n,Array:L,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:p,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:r,Float:n,Integer:s,Array:k,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:c,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}},single:{dynamic:{Boolean:r,Integer:s,Float:n,Array:x,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":v,"Array1D(3)":v,"Array1D(4)":v,"Array2D(2)":S,"Array2D(3)":S,"Array2D(4)":S,"Array3D(2)":w,"Array3D(3)":w,"Array3D(4)":w,Input:h,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:r,Float:n,Integer:s,Array:y,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":b,"Array1D(3)":b,"Array1D(4)":b,"Array2D(2)":T,"Array2D(3)":T,"Array2D(4)":T,"Array3D(2)":A,"Array3D(3)":A,"Array3D(4)":A,Input:l,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}}};t.exports={lookupKernelValueType:function(e,t,r,n){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!r)throw new Error("precision missing");n.type&&(e=n.type);const s=F[r][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===s[e])return null;if(void 0===s[e])throw new Error(`Could not find a KernelValue for ${e}`);return s[e]},kernelValueMaps:F}}),xe=e((e,t)=>{const{GLKernel:r}=D(),{FunctionBuilder:n}=o(),{WebGLFunctionNode:s}=G(),{utils:a}=i(),u=R(),{fragmentShader:l}=M(),{vertexShader:h}=O(),{glKernelString:c}=z(),{lookupKernelValueType:p}=ye();let d=null,f=null,m=null,g=null,y=null;const x=[u],b=[],v={};t.exports={WebGLKernel:class extends r{static get isSupported(){return null!==d||(this.setupFeatureChecks(),d=this.isContextMatch(m)),d}static setupFeatureChecks(){"undefined"!=typeof document?f=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(f=new OffscreenCanvas(0,0)),f&&(m=f.getContext("webgl"),m||f instanceof OffscreenCanvas||(m=f.getContext("experimental-webgl")),m&&m.getExtension&&(g={OES_texture_float:m.getExtension("OES_texture_float"),OES_texture_float_linear:m.getExtension("OES_texture_float_linear"),OES_element_index_uint:m.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:m.getExtension("WEBGL_draw_buffers")},y=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGLRenderingContext&&e instanceof WebGLRenderingContext}static getIsTextureFloat(){return Boolean(g.OES_texture_float)}static getIsDrawBuffers(){return Boolean(g.WEBGL_draw_buffers)}static getChannelCount(){return g.WEBGL_draw_buffers?m.getParameter(g.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return m.getParameter(m.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,r,n){return p(e,t,r,n)}static get testCanvas(){return f}static get testContext(){return m}static get features(){return y}static get fragmentShader(){return l}static get vertexShader(){return h}constructor(e,t){super(e,t),this.program=null,this.pipeline=t.pipeline,this.endianness=a.systemEndianness(),this.extensions={},this.argumentTextureCount=0,this.constantTextureCount=0,this.fragShader=null,this.vertShader=null,this.drawBuffersMap=null,this.maxTexSize=null,this.onRequestSwitchKernel=null,this.texture=null,this.mappedTextures=null,this.mergeSettings(e.settings||t),this.threadDim=null,this.framebuffer=null,this.buffer=null,this.textureCache=[],this.programUniformLocationCache={},this.uniform1fCache={},this.uniform1iCache={},this.uniform2fCache={},this.uniform2fvCache={},this.uniform2ivCache={},this.uniform3fvCache={},this.uniform3ivCache={},this.uniform4fvCache={},this.uniform4ivCache={}}initCanvas(){if("undefined"!=typeof document){const e=document.createElement("canvas");return e.width=2,e.height=2,e}if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(0,0)}initContext(){const e={alpha:!1,depth:!1,antialias:!1};return this.canvas.getContext("webgl",e)||this.canvas.getContext("experimental-webgl",e)}initPlugins(e){const t=[],{source:r}=this;if("string"==typeof r)for(let e=0;ee===n.name)&&t.push(n)}return t}initExtensions(){this.extensions={OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:this.context.getExtension("WEBGL_color_buffer_float")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if(!0===this.optimizeFloatMemory&&!t.isTextureFloat)throw new Error("Float textures are not supported");if("single"===this.precision&&!t.isFloatRead)throw new Error("Single precision not supported");if(this.graphical||null!==this.precision||(this.precision=t.isTextureFloat&&t.isFloatRead?"single":"unsigned"),this.subKernels&&this.subKernels.length>0&&!this.extensions.WEBGL_draw_buffers)throw new Error("could not instantiate draw buffers extension");if(null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"precision"===this.precision&&(this.precision="unsigned",console.warn("Cannot use graphical mode and single precision at the same time")),void(this.texSize=a.clone(this.output))}null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}updateMaxTexSize(){const{texSize:e,canvas:t}=this;if(null===this.maxTexSize){let r=b.indexOf(t);-1===r&&(r=b.length,b.push(t),v[r]=[e[0],e[1]]),this.maxTexSize=v[r]}this.maxTexSize[0]this.argumentNames.length)throw new Error("too many arguments for kernel");const{context:r}=this;let n=0;const s=()=>this.createTexture(),i=()=>this.constantTextureCount+n++,o=e=>{this.switchKernels({type:"argumentMismatch",needed:e})},u=()=>r.TEXTURE0+this.constantTextureCount+this.argumentTextureCount++;for(let n=0;nthis.createTexture(),onRequestIndex:()=>n++,onRequestContextHandle:()=>t.TEXTURE0+this.constantTextureCount++});this.constantBitRatios[s]=l.bitRatio,this.kernelConstants.push(l),l.setup(),l.forceUploadEachRun&&this.forceUploadKernelConstants.push(l)}}build(){if(this.built)return;if(this.initExtensions(),this.validateSettings(arguments),this.setupConstants(arguments),this.fallbackRequested)return;if(this.setupArguments(arguments),this.fallbackRequested)return;this.updateMaxTexSize(),this.translateSource();const e=this.pickRenderStrategy(arguments);if(e)return e;const{texSize:t,context:r,canvas:n}=this;r.enable(r.SCISSOR_TEST),this.pipeline&&this.precision,r.viewport(0,0,this.maxTexSize[0],this.maxTexSize[1]),n.width=this.maxTexSize[0],n.height=this.maxTexSize[1];const s=this.threadDim=Array.from(this.output);for(;s.length<3;)s.push(1);const i=this.getVertexShader(arguments),a=r.createShader(r.VERTEX_SHADER);r.shaderSource(a,i),r.compileShader(a),this.vertShader=a;const o=this.getFragmentShader(arguments),u=r.createShader(r.FRAGMENT_SHADER);if(r.shaderSource(u,o),r.compileShader(u),this.fragShader=u,this.debug&&(console.log("GLSL Shader Output:"),console.log(o)),!r.getShaderParameter(a,r.COMPILE_STATUS))throw new Error("Error compiling vertex shader: "+r.getShaderInfoLog(a));if(!r.getShaderParameter(u,r.COMPILE_STATUS))throw new Error("Error compiling fragment shader: "+r.getShaderInfoLog(u));const l=this.program=r.createProgram();r.attachShader(l,a),r.attachShader(l,u),r.linkProgram(l),this.framebuffer=r.createFramebuffer(),this.framebuffer.width=t[0],this.framebuffer.height=t[1],this.rawValueFramebuffers={};const h=new Float32Array([-1,-1,1,-1,-1,1,1,1]),c=new Float32Array([0,0,1,0,0,1,1,1]),p=h.byteLength;let d=this.buffer;d?r.bindBuffer(r.ARRAY_BUFFER,d):(d=this.buffer=r.createBuffer(),r.bindBuffer(r.ARRAY_BUFFER,d),r.bufferData(r.ARRAY_BUFFER,h.byteLength+c.byteLength,r.STATIC_DRAW)),r.bufferSubData(r.ARRAY_BUFFER,0,h),r.bufferSubData(r.ARRAY_BUFFER,p,c);const f=r.getAttribLocation(this.program,"aPos");-1!==f&&(r.enableVertexAttribArray(f),r.vertexAttribPointer(f,2,r.FLOAT,!1,0,0));const m=r.getAttribLocation(this.program,"aTexCoord");-1!==m&&(r.enableVertexAttribArray(m),r.vertexAttribPointer(m,2,r.FLOAT,!1,0,p)),r.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer);let g=0;r.useProgram(this.program);for(let e in this.constants)this.kernelConstants[g++].updateValue(this.constants[e]);this._setupOutputTexture(),null!==this.subKernels&&this.subKernels.length>0&&(this._mappedTextureSwitched={},this._setupSubOutputTextures()),this.buildSignature(arguments),this.built=!0}translateSource(){const e=n.fromKernel(this,s,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}setupReturnTypes(e){if(this.graphical||this.returnType||(this.returnType=e.getKernelResultType()),this.subKernels&&this.subKernels.length>0)for(let t=0;te.source&&this.source.match(e.functionMatch)?e.source:"").join("\n"):"\n"}_getConstantsString(){const e=[],{threadDim:t,texSize:r}=this;return this.dynamicOutput?e.push("uniform ivec3 uOutputDim","uniform ivec2 uTexSize"):e.push(`ivec3 uOutputDim = ivec3(${t[0]}, ${t[1]}, ${t[2]})`,`ivec2 uTexSize = ivec2(${r[0]}, ${r[1]})`),a.linesToString(e)}_getTextureCoordinate(){const e=this.subKernels;return null===e||e.length<1?"varying vec2 vTexCoord;\n":"out vec2 vTexCoord;\n"}_getDecode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getEncode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getDivideWithIntegerCheckString(){return this.fixIntegerDivisionAccuracy?"float divWithIntCheck(float x, float y) {\n if (floor(x) == x && floor(y) == y) {\n float q = floor(x / y + 0.5);\n if (y * q == x) {\n return q;\n }\n }\n return x / y;\n}\n\nfloat integerCorrectionModulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -(number - (divisor * floor(divWithIntCheck(number, divisor))));\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return number - (divisor * floor(divWithIntCheck(number, divisor)));\n}":""}_getMainArgumentsString(e){const t=[],{argumentNames:r}=this;for(let n=0;n{if(t.hasOwnProperty(r))return t[r];throw`unhandled artifact ${r}`})}getFragmentShader(e){return null!==this.compiledFragmentShader?this.compiledFragmentShader:this.compiledFragmentShader=this.replaceArtifacts(this.constructor.fragmentShader,this._getFragShaderArtifactMap(e))}getVertexShader(e){return null!==this.compiledVertexShader?this.compiledVertexShader:this.compiledVertexShader=this.replaceArtifacts(this.constructor.vertexShader,this._getVertShaderArtifactMap(e))}toString(){const e=a.linesToString(["const gl = context"]);return c(this.constructor,arguments,this,e)}destroy(e){if(!this.context)return;this.buffer&&this.context.deleteBuffer(this.buffer),this.framebuffer&&this.context.deleteFramebuffer(this.framebuffer);for(const e in this.rawValueFramebuffers){for(const t in this.rawValueFramebuffers[e])this.context.deleteFramebuffer(this.rawValueFramebuffers[e][t]),delete this.rawValueFramebuffers[e][t];delete this.rawValueFramebuffers[e]}if(this.vertShader&&this.context.deleteShader(this.vertShader),this.fragShader&&this.context.deleteShader(this.fragShader),this.program&&this.context.deleteProgram(this.program),this.texture){this.texture.delete();const e=this.textureCache.indexOf(this.texture.texture);e>-1&&this.textureCache.splice(e,1),this.texture=null}if(this.mappedTextures&&this.mappedTextures.length){for(let e=0;e-1&&this.textureCache.splice(r,1)}this.mappedTextures=null}if(this.kernelArguments)for(let e=0;e0;){const e=this.textureCache.pop();this.context.deleteTexture(e)}if(e){const e=b.indexOf(this.canvas);e>=0&&(b[e]=null,v[e]=null)}if(this.destroyExtensions(),delete this.context,delete this.canvas,!this.gpu)return;const t=this.gpu.kernels.indexOf(this);-1!==t&&this.gpu.kernels.splice(t,1)}destroyExtensions(){this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("WEBGL_lose_context");t&&t.loseContext()}toJSON(){const e=super.toJSON();return e.functionNodes=n.fromKernel(this,s).toJSON(),e.settings.threadDim=this.threadDim,e}}}}),be=e((e,t)=>{const n=r(),{WebGLKernel:s}=xe(),{glKernelString:i}=z();let a=null,o=null,u=null,l=null,h=null;t.exports={HeadlessGLKernel:class extends s{static get isSupported(){return null!==a||(this.setupFeatureChecks(),a=null!==u),a}static setupFeatureChecks(){if(o=null,l=null,"function"==typeof n)try{if(u=n(2,2,{preserveDrawingBuffer:!0}),!u||!u.getExtension)return;l={STACKGL_resize_drawingbuffer:u.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:u.getExtension("STACKGL_destroy_context"),OES_texture_float:u.getExtension("OES_texture_float"),OES_texture_float_linear:u.getExtension("OES_texture_float_linear"),OES_element_index_uint:u.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:u.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:u.getExtension("WEBGL_color_buffer_float")},h=this.getFeatures()}catch(e){console.warn(e)}}static isContextMatch(e){try{return"ANGLE"===e.getParameter(e.RENDERER)}catch(e){return!1}}static getIsTextureFloat(){return Boolean(l.OES_texture_float)}static getIsDrawBuffers(){return Boolean(l.WEBGL_draw_buffers)}static getChannelCount(){return l.WEBGL_draw_buffers?u.getParameter(l.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return u.getParameter(u.MAX_TEXTURE_SIZE)}static get testCanvas(){return o}static get testContext(){return u}static get features(){return h}initCanvas(){return{}}initContext(){return n(2,2,{preserveDrawingBuffer:!0})}initExtensions(){this.extensions={STACKGL_resize_drawingbuffer:this.context.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:this.context.getExtension("STACKGL_destroy_context"),OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers")}}build(){super.build.apply(this,arguments),this.fallbackRequested||this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1])}destroyExtensions(){this.extensions.STACKGL_resize_drawingbuffer=null,this.extensions.STACKGL_destroy_context=null,this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("STACKGL_destroy_context");t&&t.destroy&&t.destroy()}toString(){return i(this.constructor,arguments,this,"const gl = context || require('gl')(1, 1);\n"," if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n")}setOutput(e){return super.setOutput(e),this.graphical&&this.extensions.STACKGL_resize_drawingbuffer&&this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1]),this}}}}),ve=e((e,t)=>{const{utils:r}=i(),{WebGLFunctionNode:n}=G();t.exports={WebGL2FunctionNode:class extends n{astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const n=this.getType(e),s=r.sanitizeName(e.name);if("Infinity"===e.name)t.push("intBitsToFloat(2139095039)");else if("Boolean"===n)if(this.argumentNames.indexOf(s)>-1){const r=this.markupUserName(e.name);t.push(r.startsWith("cellShadow_")?r:`bool(${r})`)}else t.push(`user_${s}`);else t.push(this.markupUserName(e.name));return t}}}}),Te=e((e,t)=>{t.exports={fragmentShader:`#version 300 es\n__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n__SAMPLER_2D_ARRAY_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nin vec2 vTexCoord;\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x/y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n return texel[channel] * 255.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n index = index / 4;\n vec4 texel = texture(tex, st / vec2(texSize));\n return texel[channel];\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, st / vec2(texSize));\n}\n\nvec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, vec3(st / vec2(texSize), z));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n\n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),Se=e((e,t)=>{t.exports={vertexShader:"#version 300 es\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nin vec2 aPos;\nin vec2 aTexCoord;\n\nout vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),Ae=e((e,t)=>{const{WebGLKernelValueBoolean:r}=U();t.exports={WebGL2KernelValueBoolean:class extends r{}}}),we=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueFloat:n}=K();t.exports={WebGL2KernelValueFloat:class extends n{}}}),_e=e((e,t)=>{const{WebGLKernelValueInteger:r}=P();t.exports={WebGL2KernelValueInteger:class extends r{getSource(e){const t=this.getVariablePrecisionString();return"constants"===this.origin?`const ${t} int ${this.id} = ${parseInt(e)};\n`:`uniform ${t} int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),Ee=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueHTMLImage:n}=j();t.exports={WebGL2KernelValueHTMLImage:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Ie=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicHTMLImage:n}=q();t.exports={WebGL2KernelValueDynamicHTMLImage:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),ke=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:n}=W();t.exports={WebGL2KernelValueHTMLImageArray:class extends n{constructor(e,t){super(e,t),this.checkSize(e[0].width,e[0].height),this.dimensions=[e[0].width,e[0].height,e.length],this.textureSize=[e[0].width,e[0].height]}defineTexture(){const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D_ARRAY,this.texture),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MIN_FILTER,e.NEAREST)}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D_ARRAY,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage3D(t.TEXTURE_2D_ARRAY,0,t.RGBA,e[0].width,e[0].height,e.length,0,t.RGBA,t.UNSIGNED_BYTE,null);for(let r=0;r{const{utils:r}=i(),{WebGL2KernelValueHTMLImageArray:n}=ke();t.exports={WebGL2KernelValueDynamicHTMLImageArray:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:r}=e[0];this.checkSize(t,r),this.dimensions=[t,r,e.length],this.textureSize=[t,r],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Fe=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueHTMLImage:n}=Ee();t.exports={WebGL2KernelValueHTMLVideo:class extends n{}}}),$e=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueDynamicHTMLImage:n}=Ie();t.exports={WebGL2KernelValueDynamicHTMLVideo:class extends n{}}}),Ce=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleInput:n}=Y();t.exports={WebGL2KernelValueSingleInput:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;r.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),De=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleInput:n}=Ce();t.exports={WebGL2KernelValueDynamicSingleInput:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,n,s]=e.size;this.dimensions=new Int32Array([t||1,n||1,s||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ge=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedInput:n}=J();t.exports={WebGL2KernelValueUnsignedInput:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Re=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicUnsignedInput:n}=Q();t.exports={WebGL2KernelValueDynamicUnsignedInput:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Me=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:n}=ee();t.exports={WebGL2KernelValueMemoryOptimizedNumberTexture:class extends n{getSource(){const{id:e,sizeId:t,textureSize:n,dimensionsId:s,dimensions:i}=this,a=this.getVariablePrecisionString();return r.linesToString([`uniform sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${n[0]}, ${n[1]})`,`${a} ivec3 ${s} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Oe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:n}=te();t.exports={WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:class extends n{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}}}}),Ne=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueNumberTexture:n}=re();t.exports={WebGL2KernelValueNumberTexture:class extends n{getSource(){const{id:e,sizeId:t,textureSize:n,dimensionsId:s,dimensions:i}=this,a=this.getVariablePrecisionString();return r.linesToString([`uniform ${a} sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${n[0]}, ${n[1]})`,`${a} ivec3 ${s} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),ze=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicNumberTexture:n}=ne();t.exports={WebGL2KernelValueDynamicNumberTexture:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Ve=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray:n}=se();t.exports={WebGL2KernelValueSingleArray:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Be=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray:n}=Ve();t.exports={WebGL2KernelValueDynamicSingleArray:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ue=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray1DI:n}=ae();t.exports={WebGL2KernelValueSingleArray1DI:class extends n{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Ke=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray1DI:n}=Ue();t.exports={WebGL2KernelValueDynamicSingleArray1DI:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Pe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray2DI:n}=ue();t.exports={WebGL2KernelValueSingleArray2DI:class extends n{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),We=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray2DI:n}=Pe();t.exports={WebGL2KernelValueDynamicSingleArray2DI:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),je=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray3DI:n}=he();t.exports={WebGL2KernelValueSingleArray3DI:class extends n{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),qe=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray3DI:n}=je();t.exports={WebGL2KernelValueDynamicSingleArray3DI:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Xe=e((e,t)=>{const{WebGLKernelValueArray2:r}=pe();t.exports={WebGL2KernelValueArray2:class extends r{}}}),He=e((e,t)=>{const{WebGLKernelValueArray3:r}=de();t.exports={WebGL2KernelValueArray3:class extends r{}}}),Ye=e((e,t)=>{const{WebGLKernelValueArray4:r}=fe();t.exports={WebGL2KernelValueArray4:class extends r{}}}),Ze=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedArray:n}=me();t.exports={WebGL2KernelValueUnsignedArray:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Je=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicUnsignedArray:n}=ge();t.exports={WebGL2KernelValueDynamicUnsignedArray:class extends n{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Qe=e((e,t)=>{const{WebGL2KernelValueBoolean:r}=Ae(),{WebGL2KernelValueFloat:n}=we(),{WebGL2KernelValueInteger:s}=_e(),{WebGL2KernelValueHTMLImage:i}=Ee(),{WebGL2KernelValueDynamicHTMLImage:a}=Ie(),{WebGL2KernelValueHTMLImageArray:o}=ke(),{WebGL2KernelValueDynamicHTMLImageArray:u}=Le(),{WebGL2KernelValueHTMLVideo:l}=Fe(),{WebGL2KernelValueDynamicHTMLVideo:h}=$e(),{WebGL2KernelValueSingleInput:c}=Ce(),{WebGL2KernelValueDynamicSingleInput:p}=De(),{WebGL2KernelValueUnsignedInput:d}=Ge(),{WebGL2KernelValueDynamicUnsignedInput:f}=Re(),{WebGL2KernelValueMemoryOptimizedNumberTexture:m}=Me(),{WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:g}=Oe(),{WebGL2KernelValueNumberTexture:y}=Ne(),{WebGL2KernelValueDynamicNumberTexture:x}=ze(),{WebGL2KernelValueSingleArray:b}=Ve(),{WebGL2KernelValueDynamicSingleArray:v}=Be(),{WebGL2KernelValueSingleArray1DI:T}=Ue(),{WebGL2KernelValueDynamicSingleArray1DI:S}=Ke(),{WebGL2KernelValueSingleArray2DI:A}=Pe(),{WebGL2KernelValueDynamicSingleArray2DI:w}=We(),{WebGL2KernelValueSingleArray3DI:_}=je(),{WebGL2KernelValueDynamicSingleArray3DI:E}=qe(),{WebGL2KernelValueArray2:I}=Xe(),{WebGL2KernelValueArray3:k}=He(),{WebGL2KernelValueArray4:L}=Ye(),{WebGL2KernelValueUnsignedArray:F}=Ze(),{WebGL2KernelValueDynamicUnsignedArray:$}=Je(),C={unsigned:{dynamic:{Boolean:r,Integer:s,Float:n,Array:$,"Array(2)":I,"Array(3)":k,"Array(4)":L,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:f,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:r,Float:n,Integer:s,Array:F,"Array(2)":I,"Array(3)":k,"Array(4)":L,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:d,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:g,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}},single:{dynamic:{Boolean:r,Integer:s,Float:n,Array:v,"Array(2)":I,"Array(3)":k,"Array(4)":L,"Array1D(2)":S,"Array1D(3)":S,"Array1D(4)":S,"Array2D(2)":w,"Array2D(3)":w,"Array2D(4)":w,"Array3D(2)":E,"Array3D(3)":E,"Array3D(4)":E,Input:p,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:r,Float:n,Integer:s,Array:b,"Array(2)":I,"Array(3)":k,"Array(4)":L,"Array1D(2)":T,"Array1D(3)":T,"Array1D(4)":T,"Array2D(2)":A,"Array2D(3)":A,"Array2D(4)":A,"Array3D(2)":_,"Array3D(3)":_,"Array3D(4)":_,Input:c,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:m,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}}};t.exports={kernelValueMaps:C,lookupKernelValueType:function(e,t,r,n){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!r)throw new Error("precision missing");n.type&&(e=n.type);const s=C[r][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===s[e])return null;if(void 0===s[e])throw new Error(`Could not find a KernelValue for ${e}`);return s[e]}}}),et=e((e,t)=>{const{WebGLKernel:r}=xe(),{WebGL2FunctionNode:n}=ve(),{FunctionBuilder:s}=o(),{utils:a}=i(),{fragmentShader:u}=Te(),{vertexShader:l}=Se(),{lookupKernelValueType:h}=Qe();let c=null,p=null,d=null,f=null;t.exports={WebGL2Kernel:class extends r{static get isSupported(){return null!==c||(this.setupFeatureChecks(),c=this.isContextMatch(d)),c}static setupFeatureChecks(){"undefined"!=typeof document?p=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(p=new OffscreenCanvas(0,0)),p&&(d=p.getContext("webgl2"),d&&d.getExtension&&(d.getExtension("EXT_color_buffer_float"),d.getExtension("OES_texture_float_linear"),f=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext}static getFeatures(){const e=this.testContext;return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),kernelMap:!0,isTextureFloat:!0,isDrawBuffers:!0,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static getIsTextureFloat(){return!0}static getChannelCount(){return d.getParameter(d.MAX_DRAW_BUFFERS)}static getMaxTextureSize(){return d.getParameter(d.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,r,n){return h(e,t,r,n)}static get testCanvas(){return p}static get testContext(){return d}static get features(){return f}static get fragmentShader(){return u}static get vertexShader(){return l}initContext(){return this.canvas.getContext("webgl2",{alpha:!1,depth:!1,antialias:!1})}initExtensions(){this.extensions={EXT_color_buffer_float:this.context.getExtension("EXT_color_buffer_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if("single"===this.precision&&!t.isFloatRead)throw new Error("Float texture outputs are not supported");if(this.graphical||null!==this.precision||(this.precision=t.isFloatRead?"single":"unsigned"),null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"single"===this.precision&&(console.warn("Cannot use graphical mode and single precision at the same time"),this.precision="unsigned"),void(this.texSize=a.clone(this.output))}!this.graphical&&null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}translateSource(){const e=s.fromKernel(this,n,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}drawBuffers(){this.context.drawBuffers(this.drawBuffersMap)}getTextureFormat(){const{context:e}=this;switch(this.getInternalFormat()){case e.R32F:return e.RED;case e.RG32F:return e.RG;case e.RGBA32F:case e.RGBA:return e.RGBA;default:throw new Error("Unknown internal format")}}renderValues(){return void 0===this._tightRead&&this._detectTightRead(),super.renderValues()}renderKernelsToArrays(){return void 0===this._tightRead&&this._detectTightRead(),super.renderKernelsToArrays()}readFloatPixelsToFloat32Array(){if(!this._tightRead)return super.readFloatPixelsToFloat32Array();const{texSize:e,context:t}=this,r=e[0],n=e[1],s=new Float32Array(r*n);return t.readPixels(0,0,r,n,t.RED,t.FLOAT,s),s}renderOutputAsync(){return this.renderOutput!==this.renderValues?Promise.resolve(this.renderOutput()):this.renderValuesAsync()}renderValuesAsync(){void 0===this._tightRead&&this._detectTightRead();const e=this.formatValues,[t,r,n]=this.output;return this.transferValuesAsync().then(s=>e(s,t,r,n))}transferValuesAsync(){const{texSize:e,context:t}=this,r=e[0],n=e[1];let s,i,a;"single"===this.precision?(s=this._tightRead?t.RED:t.RGBA,i=t.FLOAT,a=new Float32Array(r*n*(this._tightRead?1:4))):(s=t.RGBA,i=t.UNSIGNED_BYTE,a=new Uint8Array(r*n*4));const o=t.createBuffer();t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.bufferData(t.PIXEL_PACK_BUFFER,a.byteLength,t.STREAM_READ),t.readPixels(0,0,r,n,s,i,0),t.bindBuffer(t.PIXEL_PACK_BUFFER,null);const u=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);return t.flush(),this._pollFence(u).then(()=>(t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.getBufferSubData(t.PIXEL_PACK_BUFFER,0,a),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),t.deleteBuffer(o),"single"===this.precision?a:new Float32Array(a.buffer)),e=>{throw t.deleteBuffer(o),e})}_pollFence(e){const t=this.context;return new Promise((r,n)=>{let s,i=null;"undefined"!=typeof MessageChannel?(i=new MessageChannel,i.port1.onmessage=()=>o(),s=()=>i.port2.postMessage(0)):s=()=>setTimeout(o,0);const a=(r,n)=>{t.deleteSync(e),i&&(i.port1.close(),i.port2.close()),r(n)},o=()=>{if(t.isContextLost())return a(n,new Error("WebGL context lost while awaiting kernel result"));const i=t.clientWaitSync(e,0,0);return i===t.ALREADY_SIGNALED||i===t.CONDITION_SATISFIED?a(r):i===t.WAIT_FAILED?a(n,new Error("clientWaitSync failed while awaiting kernel result")):void s()};o()})}_detectTightRead(){const e=this.context;this._tightRead=!1,e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t="Number"===this.returnType||"Float"===this.returnType||"Integer"===this.returnType||"LiteralInteger"===this.returnType;if("single"===this.precision&&!this.optimizeFloatMemory&&!this.graphical&&t&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)===e.RED&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)===e.FLOAT){if(this.formatValues===a.erectFloat)this.formatValues=a.erectMemoryOptimizedFloat;else if(this.formatValues===a.erect2DFloat)this.formatValues=a.erectMemoryOptimized2DFloat;else if(this.formatValues===a.erect3DFloat)this.formatValues=a.erectMemoryOptimized3DFloat;else if(this.formatValues!==a.erectMemoryOptimizedFloat&&this.formatValues!==a.erectMemoryOptimized2DFloat&&this.formatValues!==a.erectMemoryOptimized3DFloat)return;this._tightRead=!0}}getInternalFormat(){const{context:e}=this;if("single"===this.precision)switch(this.returnType){case"Number":case"Float":case"Integer":return this.optimizeFloatMemory?e.RGBA32F:e.R32F;case"Array(2)":return e.RG32F;case"Array(3)":case"Array(4)":return e.RGBA32F;default:throw new Error("Unhandled return type")}return e.RGBA}_setupOutputTexture(){const e=this.context;if(this.texture)return e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0),void(this._tightRead=void 0);e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t=e.createTexture(),r=this.texSize;e.activeTexture(e.TEXTURE0+this.constantTextureCount+this.argumentTextureCount),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);const n=this.getInternalFormat();"single"===this.precision?e.texStorage2D(e.TEXTURE_2D,1,n,r[0],r[1]):e.texImage2D(e.TEXTURE_2D,0,n,r[0],r[1],0,n,e.UNSIGNED_BYTE,null),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),this.texture=new this.TextureConstructor({texture:t,size:r,dimensions:this.threadDim,output:this.output,context:this.context,internalFormat:this.getInternalFormat(),textureFormat:this.getTextureFormat(),kernel:this}),this._tightRead=void 0}_setupSubOutputTextures(){const e=this.context;if(this.mappedTextures){for(let t=0;t{const{utils:r}=i(),{FunctionNode:n}=l();const s={Number:"f32",Float:"f32",Integer:"i32",LiteralInteger:"f32",Boolean:"bool","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4"},a={"===":"==","!==":"!="},o=["x","y","z","w"],u={pow:"_pow",round:"_round"},h={ceil:!0,floor:!0,_round:!0};t.exports={WGSLFunctionNode:class extends n{get requiresSequenceFreeForInit(){return!0}wgslFloat(e){if(e===1/0)return"0x1.fffffep+127";if(e===-1/0)return"-0x1.fffffep+127";if(e>34028234663852886e22)return"0x1.fffffep+127";if(e<-34028234663852886e22)return"-0x1.fffffep+127";const t=`${e}`;return-1!==t.indexOf(".")||-1!==t.indexOf("e")||-1!==t.indexOf("E")?t:`${t}.0`}wgslInt(e){return`${Math.round(e)}`}mangleFunctionName(e){return`fn_${r.sanitizeName(e)}`}getLookupType(e){return"WebGPUBuffer"===e?"Number":super.getLookupType(e)}astUpdateExpression(e,t){return this.astGeneric(e.argument,t),t.push(e.operator),t}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const r=this.getType(e.consequent),n=this.getType(e.alternate);if(null===r&&null===n)return t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t;let s="LiteralInteger"===r?"Number":r;"Integer"!==s||"Number"!==n&&"Float"!==n||(s="Number");const i=e=>{const r=this.getType(e);switch(s){case"Number":case"Float":"Integer"===r?this.castValueToFloat(e,t):"LiteralInteger"===r?this.castLiteralToFloat(e,t):this.astGeneric(e,t);break;case"Integer":"Number"===r||"Float"===r?this.castValueToInteger(e,t):"LiteralInteger"===r?this.castLiteralToInteger(e,t):this.astGeneric(e,t);break;default:this.astGeneric(e,t)}};return t.push("select("),i(e.alternate),t.push(", "),i(e.consequent),t.push(", "),this.astGeneric(e.test,t),t.push(")"),t}astFunction(e,t){if(this.isRootKernel){for(let r=0;r0&&t.push(", ");let a=this.argumentTypes[this.argumentNames.indexOf(i)];if(!a)throw this.astErrorOutput(`Unknown argument ${i} type`,e);"LiteralInteger"===a&&(this.argumentTypes[n]=a="Number");const o=s[a];if(!o)throw this.astErrorOutput(`WebGPU backend does not yet support ${a} arguments to helper functions`,e);t.push(`user_${r.sanitizeName(i)} : ${o}`)}t.push(")"),i&&t.push(` -> ${i}`),t.push(" {\n");for(let r=0;r>":!0,">>>":!0}[e.operator])return null;const r=e=>{switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer")}};return t.push("("),">>>"===e.operator?(t.push("bitcast(bitcast("),r(e.left),t.push(") >> u32("),r(e.right),t.push("))")):"<<"===e.operator||">>"===e.operator?(r(e.left),t.push(` ${e.operator} u32(`),r(e.right),t.push(")")):(r(e.left),t.push(` ${e.operator} `),r(e.right)),t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){if("~"!==e.operator)return null;switch(t.push("~("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)?t:"+"===e.operator?(this.astGeneric(e.argument,t),t):(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t)}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("f32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const n=this.getType(e),s=r.sanitizeName(e.name);return"Infinity"===e.name?(t.push("0x1.fffffep+127"),t):!this.isRootKernel||-1===this.argumentNames.indexOf(e.name)||"Number"!==n&&"Float"!==n&&"Integer"!==n&&"Boolean"!==n?(t.push(`user_${s}`),t):("Boolean"===n?t.push(`bool(params.user_${s})`):t.push(`params.user_${s}`),t)}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const r=[],n=[],s=[],i=[];let a=null;if(e.init){const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,r);for(let e=0;e0&&t.push(r.join(""),"\n"),t.push(`for (var ${e} : i32 = 0;${e}0&&t.push(`if (!(${n.join("")})) { break; }\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=this.getInternalVariableName("safeI");return t.push(`for (var ${r} : i32 = 0;${r}{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&t(e[r]))return!0;return!1};if(t(r[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",r[e])}for(let e=0;ee+1){u=!0,this.astSwitchCaseConsequent(n[e].consequent,o);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(n[e].consequent,t),t.push("\n}")}return u&&(t.push(" else {"),t.push(o.join("")),t.push("}")),t.push("\n"),t}astThisExpression(e,t){return t.push("this"),t}astSequenceExpression(e,t){const{expressions:r}=e;if(1===r.length)return this.astGeneric(r[0],t),t;throw this.astErrorOutput("WebGPU backend does not yet support the comma operator",e)}astMemberExpression(e,t){const{property:n,name:i,signature:a,origin:o,type:u,xProperty:l,yProperty:h,zProperty:c}=this.getMemberExpressionDetails(e);switch(a){case"value.thread.value":case"this.thread.value":if("x"!==i&&"y"!==i&&"z"!==i)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`i32(threadGid.${i})`),t;case"this.output.value":{const r={x:0,y:1,z:2}[i];if(void 0===r)throw this.astErrorOutput("Unexpected expression",e);if(this.dynamicOutput){const e=`params.output${i.toUpperCase()}`;this.isState("casting-to-float")?t.push(`f32(${e})`):t.push(`i32(${e})`)}else this.isState("casting-to-integer")?t.push(`${this.output[r]}`):t.push(`${this.output[r]}.0`);return t}case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===o)return t.push(this.wgslFloat(Math[i])),t;switch(n){case"r":return t.push(`user_${r.sanitizeName(i)}.x`),t;case"g":return t.push(`user_${r.sanitizeName(i)}.y`),t;case"b":return t.push(`user_${r.sanitizeName(i)}.z`),t;case"a":return t.push(`user_${r.sanitizeName(i)}.w`),t}break;case"this.constants.value":{const r=this.constants[i];switch(u){case"Integer":return this.isState("casting-to-float")?t.push(this.wgslFloat(r)):t.push(this.wgslInt(r)),t;case"Number":case"Float":return this.isState("casting-to-integer")?t.push(this.wgslInt(r)):t.push(this.wgslFloat(r)),t;case"Boolean":return t.push(r?"true":"false"),t;case"Array(2)":case"Array(3)":case"Array(4)":{const e=parseInt(u.substring(6),10),n=[];for(let t=0;t4)throw this.astErrorOutput("this.color takes (r, g, b) or (r, g, b, a)",e);t.push("kernelColor(data_index");for(let r=0;r0&&t.push(", "),s){case"Integer":this.castValueToFloat(n,t);break;case"LiteralInteger":this.castLiteralToFloat(n,t);break;default:this.astGeneric(n,t)}}else{const s=this.lookupFunctionArgumentTypes(n)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(n,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("i32("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("f32("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.astGeneric(a,t);continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){"Identifier"===a.type?t.push(`user_${r.sanitizeName(a.name)}`):this.astGeneric(a,t);continue}break;case"Array":case"Array2D":case"Array3D":case"Input":case"WebGPUBuffer":throw this.astErrorOutput("WebGPU backend does not yet support array arguments to helper functions",e)}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),a&&t.push(")"),t}astArrayExpression(e,t){switch(this.getType(e)){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":throw this.astErrorOutput("WebGPU backend does not yet support Matrix types",e)}const r=e.elements.length;t.push(`vec${r}(`);for(let n=0;n0&&t.push(", ");const r=e.elements[n];switch(this.getType(r)){case"Integer":this.castValueToFloat(r,t);break;case"LiteralInteger":this.castLiteralToFloat(r,t);break;default:this.astGeneric(r,t)}}return t.push(")"),t}memberExpressionXYZ(e,t,r,n){return r?n.push(this.memberExpressionPropertyMarkup(r),", "):n.push("0, "),t?n.push(this.memberExpressionPropertyMarkup(t),", "):n.push("0, "),n.push(this.memberExpressionPropertyMarkup(e)),n}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("building-integer");break;default:this.astGeneric(e,t)}return t.join("")}}}}),rt=e((e,t)=>{let r=null;t.exports={WebGPUContext:class e{static get isSupported(){return"undefined"!=typeof navigator&&!!navigator.gpu}static acquire(){if(r)return r;const t=(async()=>{if(!e.isSupported)throw new Error("WebGPU is not supported on this platform (navigator.gpu is missing)");const n=await navigator.gpu.requestAdapter();if(!n)throw new Error("WebGPU is present (navigator.gpu) but no adapter is available. On headless Chromium there is no adapter; run headed. Use `await GPU.isWebGPUAvailable()` to feature-detect.");const s=await n.requestDevice({requiredLimits:{maxStorageBufferBindingSize:n.limits.maxStorageBufferBindingSize,maxBufferSize:n.limits.maxBufferSize}}),i={adapter:n,device:s,isLost:!1};return s.lost.then(e=>{i.isLost=!0,"destroyed"!==e.reason&&console.error(`gpu.js [webgpu]: device lost: ${e.message}`),r===t&&(r=null)}),s.onuncapturederror=e=>{console.error(`gpu.js [webgpu]: ${e.error.message}`)},i})();return t.catch(()=>{r===t&&(r=null)}),r=t}static destroy(){if(!r)return Promise.resolve();const e=r;return r=null,e.then(({device:e})=>{e.destroy()},()=>{})}}}}),nt=e((e,t)=>{t.exports={WebGPUBufferResult:class e{constructor(e){this.buffer=e.buffer,this.output=e.output,this.componentCount=e.componentCount||1,this.context=e.context,this.kernel=e.kernel,this.type="WebGPUBuffer",this._deleted=!1,this.buffer._refs?this.buffer._refs++:this.buffer._refs=1}toArray(){return this._deleted?Promise.reject(new Error("WebGPUBufferResult has been deleted")):this.kernel.readBufferResult(this)}delete(){this._deleted||(this._deleted=!0,0===--this.buffer._refs&&this.buffer.destroy())}clone(){return new e(this)}}}}),st=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:s}=o(),{WGSLFunctionNode:u}=tt(),{WebGPUContext:l}=rt(),{WebGPUBufferResult:h}=nt(),{utils:c}=i(),{Input:p}=n(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0}),f={_pow:"fn _pow(v1 : f32, v2 : f32) -> f32 {\n if (v2 == 0.0) { return 1.0; }\n return pow(v1, v2);\n}",_round:"fn _round(x : f32) -> f32 {\n return floor(x + 0.5);\n}",cbrt:"fn cbrt(x : f32) -> f32 {\n return sign(x) * pow(abs(x), 1.0 / 3.0);\n}",expm1:"fn expm1(x : f32) -> f32 {\n return exp(x) - 1.0;\n}",fround:"fn fround(x : f32) -> f32 {\n return x;\n}",imul:"fn imul(a : f32, b : f32) -> f32 {\n return f32(i32(a) * i32(b));\n}",log10:`fn log10(x : f32) -> f32 {\n return log2(x) * ${1/Math.log2(10)};\n}`,log1p:"fn log1p(x : f32) -> f32 {\n return log(1.0 + x);\n}",clz32:"fn clz32(x : f32) -> f32 {\n return f32(countLeadingZeros(u32(x)));\n}"};t.exports={WebGPUKernel:class extends r{static get isSupported(){return l.isSupported}static get isAsync(){return!0}static isContextMatch(e){return Boolean(e&&"function"==typeof e.createShaderModule&&"function"==typeof e.createComputePipeline)}static getFeatures(){return d}static get features(){return d}static get mode(){return"webgpu"}static getSignature(e,t){return"webgpu"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static nativeFunctionArguments(){throw new Error("WebGPU backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebGPU backend does not yet support native functions")}static combineKernels(){throw new Error("WebGPU backend does not yet support combineKernels; chain kernels with `await` and pipeline mode instead")}constructor(e,t){if(super(e,t),t){if("unsigned"===t.precision&&!t.graphical)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(t.subKernels)throw new Error("WebGPU backend does not yet support createKernelMap")}this.mergeSettings(e.settings||t),(null===this.precision||this.graphical)&&(this.precision="single"),this.asyncMode=!0,this.threadDim=null,this.componentCount=1,this.compiledSource=null,this.translatedBody=null,this.translatedFunctions=null,this.paramsLayout=null,this._buildPromise=null,this._device=null,this.computePipeline=null,this.bindGroupLayout=null,this.bindGroup=null,this.bindGroupDirty=!0,this.paramsBuffer=null,this.paramsMirror=null,this.outputBuffer=null,this.argumentBuffers=null,this.constantBuffers=null,this.stagingPool=[],this._canvasContext=null,this._blitPipeline=null,this._blitParamsBuffer=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built){if(!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");if(t.length!==this.output.length)throw new Error("WebGPU backend does not yet support changing the output rank of a built kernel; the workgroup shape is fixed at build")}return this.output=t,this}toString(){throw new Error("WebGPU backend does not yet support toString")}validateSettings(e){if(this.graphical){if(!this.output||2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");if(this.pipeline)throw new Error("graphical mode and pipeline mode are mutually exclusive");if(!this.canvas)throw new Error("graphical mode requires a canvas (none could be created; pass one in settings)")}if("unsigned"===this.precision)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(this.precision="single",this.subKernels&&this.subKernels.length>0)throw new Error("WebGPU backend does not yet support createKernelMap");if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=Array.from(c.getDimensions(e[0]));else{if("WebGPUBuffer"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(e[0].output)}}this.checkOutput()}setupArguments(e){super.setupArguments(e);for(let e=0;e,`);for(let e=0;e params : Params;");for(let t=0;t user_${e[t].name} : array;`);const i=1+e.length;n.push(`@group(0) @binding(${i}) var result : array;`),this.graphical&&n.push("fn kernelColor(index : i32, r : f32, g : f32, b : f32, a : f32) {\n result[index * 4] = r;\n result[index * 4 + 1] = g;\n result[index * 4 + 2] = b;\n result[index * 4 + 3] = a;\n}");for(let e=0;e constants_${r[e].name} : array;`);n.push("var threadGid : vec3;"),null!==this.paramsLayout.randomSeedOffset&&n.push("var pcgState : u32;\nfn pcg_random() -> f32 {\n pcgState = pcgState * 747796405u + 2891336453u;\n let word = ((pcgState >> ((pcgState >> 28u) + 4u)) ^ pcgState) * 277803737u;\n let mixed = (word >> 22u) ^ word;\n return f32(mixed >> 8u) / 16777216.0;\n}");const a=`${this.translatedFunctions}\n${this.translatedBody}`;/\bLOOP_MAX\b/.test(a)&&n.push(`const LOOP_MAX : i32 = ${parseInt(this.loopMaxIterations,10)||1e3};`);for(const e in f)new RegExp(`\\b${e}\\(`).test(a)&&n.push(f[e]);for(let t=0;t f32 {\n return user_${r}[u32(x + i32(params.user_${r}_dims.x) * (y + i32(params.user_${r}_dims.y) * z))];\n}`)}for(let e=0;e f32 {\n return constants_${t.name}[u32(x + ${i[0]} * (y + ${i[1]} * z))];\n}`)}this.translatedFunctions&&n.push(this.translatedFunctions);const o=1===this.output.length?[64,1,1]:[8,8,1];return this.workgroupSize=o,1===this.output.length?n.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n let flat_index : u32 = gid.x + gid.y * params.dispatchWidth;\n threadGid = vec3(flat_index, 0u, 0u);\n if (flat_index >= params.outputX) { return; }\n let data_index : i32 = i32(flat_index);\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`):n.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n threadGid = gid;\n if (gid.x >= params.outputX || gid.y >= params.outputY || gid.z >= params.outputZ) { return; }\n let data_index : i32 = i32(gid.x + params.outputX * (gid.y + params.outputY * gid.z));\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`),n.join("\n")}constantDimensions(e){const t=e instanceof p?Array.from(e.size):Array.from(c.getDimensions(e));for(;t.length<3;)t.push(1);return t}async _buildAsync(){const e=await l.acquire();this.context=e;const t=this._device=e.device,r=t.createShaderModule({code:this.compiledSource}),n=(await r.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(n.length>0)throw new Error("Error compiling WGSL compute shader:\n"+n.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n")+`\n--- generated WGSL ---\n${this.compiledSource}`);const{arrayArgs:s,bufferConstants:i,byteLength:a}=this.paramsLayout,o=[{binding:0,visibility:4,buffer:{type:"uniform"}}];for(let e=0;ei&&(s[1]=Math.ceil(s[0]/i),s[0]=Math.ceil(s[0]/s[1])),a=s[0]*t);for(let e=0;e<3;e++)if(s[e]>i)throw new Error(`output dimension ${e} needs ${s[e]} workgroups, over this device's limit of ${i}`);return{groups:s,dispatchWidth:a}}async _buildBlitPipeline(e){if(this.canvas.width=this.output[0],this.canvas.height=this.output[1],this._canvasContext=this.canvas.getContext("webgpu"),!this._canvasContext)throw new Error("could not get a webgpu context from the canvas");const t=navigator.gpu.getPreferredCanvasFormat();this._canvasContext.configure({device:e,format:t,alphaMode:"premultiplied"});const r=e.createShaderModule({code:"struct BlitParams { width : u32, height : u32, pad0 : u32, pad1 : u32 }\n@group(0) @binding(0) var blit : BlitParams;\n@group(0) @binding(1) var pixels : array;\n@vertex fn vs(@builtin(vertex_index) vi : u32) -> @builtin(position) vec4 {\n var pos = array, 3>(vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));\n return vec4(pos[vi], 0.0, 1.0);\n}\n@fragment fn fs(@builtin(position) pos : vec4) -> @location(0) vec4 {\n let x = u32(pos.x);\n let y = u32(pos.y);\n let row = blit.height - 1u - y;\n let i = (row * blit.width + x) * 4u;\n let a = pixels[i + 3u];\n return vec4(pixels[i] * a, pixels[i + 1u] * a, pixels[i + 2u] * a, a);\n}"}),n=(await r.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(n.length>0)throw new Error("Error compiling the graphical blit shader:\n"+n.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n"));this._blitBindGroupLayout=e.createBindGroupLayout({entries:[{binding:0,visibility:2,buffer:{type:"uniform"}},{binding:1,visibility:2,buffer:{type:"read-only-storage"}}]}),this._blitPipeline=e.createRenderPipeline({layout:e.createPipelineLayout({bindGroupLayouts:[this._blitBindGroupLayout]}),vertex:{module:r,entryPoint:"vs"},fragment:{module:r,entryPoint:"fs",targets:[{format:t}]},primitive:{topology:"triangle-list"}}),this._blitParamsBuffer=e.createBuffer({size:16,usage:72})}_ensureOutputBuffer(){const[e,t,r]=this.threadDim,n=e*t*r*4*this.componentCount;this.immutable&&this.pipeline&&this.outputBuffer&&(0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this.outputBuffer=null,this.bindGroupDirty=!0),this.outputBuffer&&this.outputBuffer.size>=n||(this.outputBuffer&&0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this._checkBufferSize(n,`output [${this.output.join(", ")}]`),this.outputBuffer=this._device.createBuffer({size:n,usage:132}),this.outputBuffer._refs=1,this.bindGroupDirty=!0)}_checkBufferSize(e,t){const r=this._device.limits,n=Math.min(r.maxStorageBufferBindingSize,r.maxBufferSize);if(e>n)throw new Error(`WebGPU backend: ${t} needs ${e} bytes but this device allows ${n} per storage buffer (maxStorageBufferBindingSize/maxBufferSize); reduce the output or split the work across kernels`)}_snapshotArguments(e){const t=new Array(e.length);for(let r=0;rthis._runInternal(e))}_runInternal(e){if(this.context&&this.context.isLost)throw new Error("WebGPU device was lost; call kernel.destroy() (or gpu.destroy()) and run again to rebuild on a fresh device");const t=this._device,r=t.queue,{arrayArgs:n,scalarArgs:s,bufferConstants:i}=this.paramsLayout,a=this.threadDim=Array.from(this.output);for(;a.length<3;)a.push(1);if(this._ensureOutputBuffer(),null!==this.paramsLayout.randomSeedOffset){const e=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0;this.paramsU32[this.paramsLayout.randomSeedOffset/4]=e}this.paramsU32[0]=a[0],this.paramsU32[1]=a[1],this.paramsU32[2]=a[2],this.paramsU32[3]=this._computeDispatch(a).dispatchWidth;for(let s=0;s{const e=new Float32Array(p.buffer.getMappedRange(0,u).slice(0));return p.buffer.unmap(),this._releaseStaging(p),this._shapeOutput(e,d,this.componentCount)},e=>{throw this._releaseStaging(p),e})}_acquireStaging(e){for(let t=0;t=e)return r.busy=!0,r}const t={buffer:this._device.createBuffer({size:e,usage:9}),size:e,busy:!0,pooled:this.stagingPool.length<3};return t.pooled&&this.stagingPool.push(t),t}_releaseStaging(e){e.pooled?e.busy=!1:e.buffer.destroy()}_shapeOutput(e,t,r){const[n,s,i]=[t[0],t[1]||1,t[2]||1];if(1===r)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,n);case 2:return c.erectMemoryOptimized2DFloat(e,n,s);default:return c.erectMemoryOptimized3DFloat(e,n,s,i)}const a=r,o=t=>{const r=new Array(n);for(let s=0;s{const t=new Float32Array(i.buffer.getMappedRange(0,s).slice(0));return i.buffer.unmap(),this._releaseStaging(i),this._shapeOutput(t,r,e.componentCount)},e=>{throw this._releaseStaging(i),e})}getPixels(e){if(!this.graphical)return Promise.reject(new Error("getPixels only works on a graphical kernel"));if(!this.outputBuffer)return Promise.reject(new Error("run the kernel before reading its pixels"));const[t,r]=this.output,n=t*r*4*4,s=this._acquireStaging(n),i=this._device.createCommandEncoder();return i.copyBufferToBuffer(this.outputBuffer,0,s.buffer,0,n),this._device.queue.submit([i.finish()]),s.buffer.mapAsync(1,0,n).then(()=>{const i=new Float32Array(s.buffer.getMappedRange(0,n).slice(0));s.buffer.unmap(),this._releaseStaging(s);const a=new Uint8ClampedArray(t*r*4);for(let n=0;n{throw this._releaseStaging(s),e})}destroy(e){if(this._blitParamsBuffer&&(this._blitParamsBuffer.destroy(),this._blitParamsBuffer=null),this._canvasContext&&(this._canvasContext.unconfigure(),this._canvasContext=null),this._blitPipeline=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null,this.paramsBuffer&&(this.paramsBuffer.destroy(),this.paramsBuffer=null),this.paramsLayout)for(let e=0;e{const r={i32:127,i64:126,f32:125,f64:124,v128:123},n=new DataView(new ArrayBuffer(16));function s(e,t){let r=e>>>0;do{let e=127&r;r>>>=7,0!==r&&(e|=128),t.push(e)}while(0!==r)}function i(e,t){let r=0|e;for(;;){const e=127&r;if(r>>=7,0===r&&!(64&e)||-1===r&&64&e)return void t.push(e);t.push(128|e)}}function a(e,t,r){let n=e>>>0;for(let e=0;e<4;e++)t[r+e]=127&n|128,n>>>=7;t[r+4]=127&n}function o(e,t){const r=[];for(let t=0;t65535&&t++,n<128?r.push(n):n<2048?r.push(192|n>>6,128|63&n):n<65536?r.push(224|n>>12,128|n>>6&63,128|63&n):r.push(240|n>>18,128|n>>12&63,128|n>>6&63,128|63&n)}s(r.length,t);for(let e=0;e3)throw new Error(`WasmModuleBuilder: lane index ${t} out of range for 4-lane shape`);return this.bytes.push(253,e,t),this}_push(e){for(let t=0;t${t.join(",")}`;if(r in this.typeIndexByKey)return this.typeIndexByKey[r];const n=this.types.length;return this.types.push({params:e,results:t}),this.typeIndexByKey[r]=n,n}addMemoryImport(e,t,r=!1){if(r&&null==t)throw new Error("WasmModuleBuilder: shared memory import requires a maximum");return this.memoryImport={initial:e,maximum:t,shared:r},this}addFuncImport(e,t,r,n="env"){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);const s=this.funcImports.length;return this.funcImports.push({name:e,module:n,typeIndex:this._typeIndex(t,r)}),this.funcImportIndexByName[e]=s,s}addGlobal(e,t,r){return u(e),this.globals.push({type:e,mutable:t,initialValue:r}),this.globals.length-1}addFunction(e,{params:t=[],results:r=[],locals:n=[]}={}){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);t.forEach(u),r.forEach(u),n.forEach(u);const s=new h(this,e,t,r,n);return this.functionIndexByName[e]=this.functions.length,this.functions.push({name:e,emitter:s,typeIndex:this._typeIndex(t,r)}),s}exportFunction(e,t=e){return this.exports.push({name:e,exportName:t}),this}_resolveFuncIndex(e){if(e in this.funcImportIndexByName)return this.funcImportIndexByName[e];if(e in this.functionIndexByName)return this.funcImports.length+this.functionIndexByName[e];throw new Error(`WasmModuleBuilder: call target "${e}" is not an import or a defined function`)}_section(e,t,r){r.push(e),s(t.length,r);for(let e=0;e0){const t=[];s(this.types.length,t);for(const{params:e,results:r}of this.types){t.push(96),s(e.length,t);for(const r of e)t.push(u(r));s(r.length,t);for(const e of r)t.push(u(e))}this._section(1,t,e)}if(null!==this.memoryImport||this.funcImports.length>0){const t=[];if(s((null!==this.memoryImport?1:0)+this.funcImports.length,t),null!==this.memoryImport){const{initial:e,maximum:r,shared:n}=this.memoryImport;o("env",t),o("memory",t),t.push(2);const i=null!=r;t.push(n?3:i?1:0),s(e,t),i&&s(r,t)}for(const{name:e,module:r,typeIndex:n}of this.funcImports)o(r,t),o(e,t),t.push(0),s(n,t);this._section(2,t,e)}if(this.functions.length>0){const t=[];s(this.functions.length,t);for(const{typeIndex:e}of this.functions)s(e,t);this._section(3,t,e)}if(this.globals.length>0){const t=[];s(this.globals.length,t);for(const{type:e,mutable:r,initialValue:s}of this.globals){if(t.push(u(e),r?1:0),"i32"===e)t.push(65),i(s,t);else if("f32"===e){t.push(67),n.setFloat32(0,s,!0);for(let e=0;e<4;e++)t.push(n.getUint8(e))}else{if("v128"!==e)throw new Error(`WasmModuleBuilder: no initializer encoding for global type "${e}"`);t.push(253,12);for(let e=0;e<16;e++)t.push(0)}t.push(11)}this._section(6,t,e)}if(this.exports.length>0){const t=[];s(this.exports.length,t);for(const{name:e,exportName:r}of this.exports)o(r,t),t.push(0),s(this._resolveFuncIndex(e),t);this._section(7,t,e)}if(this.functions.length>0){const t=[];s(this.functions.length,t);for(const{emitter:e}of this.functions){const r=e.bytes.slice();for(const{at:t,name:n}of e.callFixups)a(this._resolveFuncIndex(n),r,t);const n=[],i=[];for(const t of e.locals){const e=u(t);i.length>0&&i[i.length-1].type===e?i[i.length-1].count++:i.push({type:e,count:1})}s(i.length,n);for(const{type:e,count:t}of i)s(t,n),n.push(e);for(let e=0;e{const{utils:r}=i(),{FunctionNode:n}=l(),{WasmFunctionEmitter:s}=it();var a=class{constructor(){this.localCount=0}addLocal(){return this.localCount++}};for(const e of Object.getOwnPropertyNames(s.prototype))"constructor"!==e&&"addLocal"!==e&&"function"==typeof s.prototype[e]&&(a.prototype[e]=function(){return this});const o={sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,sinh:1,cosh:1,tanh:1,asinh:1,acosh:1,atanh:1,exp:1,expm1:1,log:1,log2:1,log10:1,log1p:1,cbrt:1,pow:2,sign:1},u={abs:"f32Abs",floor:"f32Floor",ceil:"f32Ceil",sqrt:"f32Sqrt",trunc:"f32Trunc"},h={"+":"f32Add","-":"f32Sub","*":"f32Mul"},c={"+":"i32Add","-":"i32Sub","*":"i32Mul"},p={"==":"f32Eq","===":"f32Eq","!=":"f32Ne","!==":"f32Ne","<":"f32Lt",">":"f32Gt","<=":"f32Le",">=":"f32Ge"},d={"==":"i32Eq","===":"i32Eq","!=":"i32Ne","!==":"i32Ne","<":"i32LtS",">":"i32GtS","<=":"i32LeS",">=":"i32GeS"},f={"&":"i32And","|":"i32Or","^":"i32Xor","<<":"i32Shl",">>":"i32ShrS",">>>":"i32ShrU"},m={"+":"f32x4Add","-":"f32x4Sub","*":"f32x4Mul"},g={"+":"i32x4Add","-":"i32x4Sub","*":"i32x4Mul"},y={"==":"f32x4Eq","===":"f32x4Eq","!=":"f32x4Ne","!==":"f32x4Ne","<":"f32x4Lt",">":"f32x4Gt","<=":"f32x4Le",">=":"f32x4Ge"},x={"==":"i32x4Eq","===":"i32x4Eq","!=":"i32x4Ne","!==":"i32x4Ne","<":"i32x4LtS",">":"i32x4GtS","<=":"i32x4LeS",">=":"i32x4GeS"},b={"<<":"i32x4Shl",">>":"i32x4ShrS",">>>":"i32x4ShrU"},v={abs:"f32x4Abs",floor:"f32x4Floor",ceil:"f32x4Ceil",sqrt:"f32x4Sqrt",trunc:"f32x4Trunc"};function T(e){switch(e){case"Number":case"Float":case"LiteralInteger":return"f32";case"Integer":case"Boolean":return"i32";default:throw new Error(`WebAssembly backend does not yet support ${e} arguments to helper functions`)}}t.exports={WebAssemblyFunctionNode:class extends n{constructor(e,t){super(e,t),this.assembler=null,this.em=null,this.locals=null,this.depth=0,this.loopStack=null,this.usedMathImports=new Set,this.usesRandom=!1,this.readsThread=!1,this.taintedLocals=null,this.uniformity=[],this._analysisDone=!1,this._analysisPass=!1,this.vec=!1,this.vMaskDepth=0,this.vCur=-1,this.vRetMask=-1,this.vTerminated=!1,this.vInfo=null,this._vBaseX=-1}mangleFunctionName(e){return`fn_${r.sanitizeName(e)}`}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}toString(){return this._analysisDone||(this._analysisDone=!0,this._analysisPass=!0,this.walkFunction(new a),this._analysisPass=!1),""}emitFunction(e){this.assembler=e;const{module:t}=e;let r;if(this.isRootKernel)r=t.addFunction("kernel",{params:[],results:[]});else{const e=this.argumentTypes.map(e=>T("LiteralInteger"===e?"Number":e)),n=[];if(this.returnType)switch(this.returnType){case"Integer":case"Boolean":n.push("i32");break;case"Number":case"Float":case"LiteralInteger":n.push("f32");break;default:throw new Error(`WebAssembly backend does not yet support helper functions returning ${this.returnType}`)}r=t.addFunction(this.mangleFunctionName(this.name),{params:e,results:n})}return this.walkFunction(r),!this.isRootKernel&&this.returnType&&r.unreachable(),r}walkFunction(e){this.em=e,this.locals=new Map,this.depth=0,this.loopStack=[],this.taintedLocals=new Set;const t=this.getJsAST();if(this.isRootKernel)for(const r of this.collectAssignedArgumentNames(t)){const t=this.argumentNames.indexOf(r),n=this.argumentTypes[t];if("Number"!==n&&"Float"!==n&&"Integer"!==n&&"Boolean"!==n)continue;const s=this.assembler?this.assembler.layout.scalars[r]:null,i=s?s.offset:0,a="Integer"===n||"Boolean"===n?"i32":"f32",o=e.addLocal(a);e.i32Const(0),"i32"===a?e.i32Load(i):e.f32Load(i),e.localSet(o),this.locals.set(r,{kind:"scalar",index:o,wtype:a,gtype:n})}if(!this.isRootKernel){for(let e=0;e{if(n&&"object"==typeof n){if(Array.isArray(n))return n.forEach(r);if("FunctionDeclaration"!==n.type||n===e){"AssignmentExpression"===n.type&&"Identifier"===n.left.type&&-1!==this.argumentNames.indexOf(n.left.name)&&t.add(n.left.name),"UpdateExpression"===n.type&&"Identifier"===n.argument.type&&-1!==this.argumentNames.indexOf(n.argument.name)&&t.add(n.argument.name);for(const e in n){if("loc"===e||"start"===e||"end"===e||"parent"===e)continue;const t=n[e];t&&"object"==typeof t&&r(t)}}}};return r(e.body),t}enterBlock(e){this.em.block(e),this.depth++}enterLoop(e){this.em.loop(e),this.depth++}enterIf(e){this.em.if_(e),this.depth++}exit(){this.em.end(),this.depth--}brTo(e){this.em.br(this.depth-e)}brIfTo(e){this.em.brIf(this.depth-e)}get loopMax(){return parseInt(this.loopMaxIterations,10)||1e3}coerce(e,t){if(e===t)return t;if("void"===e)throw new Error("cannot use a void expression as a value");switch(t){case"f32":return this.em.f32ConvertI32S(),"f32";case"i32":return"f32"===e&&this.em.i32TruncSatF32S(),"i32";case"bool":return"f32"===e?this.em.f32Const(0).f32Ne():this.em.i32Eqz().i32Eqz(),"bool";default:throw new Error(`unknown wasm value category ${t}`)}}castLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castLiteralToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}castValueToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castValueToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}emitByType(e,t){const r=this.getType(e);return"f32"===t?"Integer"===r?this.castValueToFloat(e):"LiteralInteger"===r?this.castLiteralToFloat(e):(this.coerce(this.expression(e),"f32"),"f32"):"Number"===r||"Float"===r?this.castValueToInteger(e):"LiteralInteger"===r?this.castLiteralToInteger(e):(this.coerce(this.expression(e),"i32"),"i32")}emitCondition(e){const t=this.expression(e);if("bool"!==t)if("i32"!==t){if("f32"!==t)throw this.astErrorOutput("cannot use a void expression as a condition",e);this.em.f32Const(0).f32Ne()}else this.em.i32Eqz().i32Eqz()}statement(e){switch(e.type){case"VariableDeclaration":return this.stmtVariableDeclaration(e);case"ExpressionStatement":return this.statementExpression(e.expression);case"ReturnStatement":return this.stmtReturn(e);case"IfStatement":return this.stmtIf(e);case"ForStatement":return this.stmtFor(e);case"WhileStatement":return this.stmtWhile(e);case"DoWhileStatement":return this.stmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.castValueToFloat(s));else switch(i.valueType=u,u){case"Number":case"Float":this.setScalarLocal(o,"f32",u,()=>{"LiteralInteger"===a?this.castLiteralToFloat(s):"Integer"===a?this.castValueToFloat(s):this.coerce(this.expression(s),"f32")});break;case"Integer":this.setScalarLocal(o,"i32","Integer",()=>{"LiteralInteger"===a?this.castLiteralToInteger(s):"Number"===a||"Float"===a?this.castValueToInteger(s):this.coerce(this.expression(s),"i32")});break;case"Boolean":this.setScalarLocal(o,"i32","Boolean",()=>this.emitCondition(s));break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${u}`,e)}this.isThreadDependent(s)&&this.taintedLocals.add(o)}}setScalarLocal(e,t,r,n){let s=this.locals.get(e);s&&"scalar"===s.kind&&s.wtype===t?s.gtype=r:(s={kind:"scalar",index:this.em.addLocal(t),wtype:t,gtype:r},this.locals.set(e,s)),n(),this.em.localSet(s.index)}declareVecLocal(e,t,r,n,s){const i=parseInt(t.substring(6),10);n.valueType=t;let a=this.locals.get(e);if(!a||"vec"!==a.kind||a.n!==i){const r=[];for(let e=0;ethis.em.localSet(r.index);else{if(r||!this.isRootKernel||-1===this.argumentNames.indexOf(t))throw this.astErrorOutput(`cannot assign to "${t}"`,e);{const r=this.argumentTypes[this.argumentNames.indexOf(t)],i=this.assembler?this.assembler.layout.scalars[t]:null;if(this.assembler&&!i)throw this.astErrorOutput(`WebAssembly backend does not yet support assigning to the array argument "${t}"`,e);const a=i?i.offset:0;n="Integer"===r||"Boolean"===r?"i32":"f32",this.em.i32Const(0),s=()=>"i32"===n?this.em.i32Store(a):this.em.f32Store(a)}}if("="===e.operator){const t=this.getType(e.left),r=this.getType(e.right);"Integer"!==t&&"Integer"===r?(this.castValueToFloat(e.right),this.coerce("f32",n)):"Integer"!==t&&"LiteralInteger"===r?(this.castLiteralToFloat(e.right),this.coerce("f32",n)):"Integer"===t&&"LiteralInteger"===r?(this.castLiteralToInteger(e.right),this.coerce("i32",n)):"Integer"!==t||"Number"!==r&&"Float"!==r?this.coerce(this.expression(e.right),n):(this.castValueToInteger(e.right),this.coerce("i32",n))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.coerce(this.exprBinary(t),n)}s(),(this.isThreadDependent(e.right)||"="!==e.operator&&this.taintedLocals.has(t))&&this.taintedLocals.add(t)}emitUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const r=this.locals.get(e.argument.name);if(!r||"scalar"!==r.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const n="i32"===r.wtype,s=()=>n?this.em.i32Const(1):this.em.f32Const(1),i="++"===e.operator?n?"i32Add":"f32Add":n?"i32Sub":"f32Sub";return t?(this.em.localGet(r.index),s(),this.em[i]().localSet(r.index),"void"):(e.prefix?(this.em.localGet(r.index),s(),this.em[i]().localTee(r.index)):(this.em.localGet(r.index).localGet(r.index),s(),this.em[i]().localSet(r.index)),r.wtype)}stmtReturn(e){if(!e.argument){if(this.isRootKernel)return void this.em.return_();throw this.astErrorOutput("Unexpected return statement",e)}this.pushState("skip-literal-correction");const t=this.getType(e.argument);if(this.popState("skip-literal-correction"),this.returnType||(this.returnType="LiteralInteger"===t||"Integer"===t?"Number":t),this.isRootKernel)return this.stmtRootReturn(e,t);if(this.isSubKernel)throw this.astErrorOutput("WebAssembly backend does not yet support createKernelMap",e);switch(this.returnType){case"LiteralInteger":case"Number":case"Float":"Integer"===t?this.castValueToFloat(e.argument):"LiteralInteger"===t?this.castLiteralToFloat(e.argument):this.coerce(this.expression(e.argument),"f32");break;case"Integer":"Float"===t||"Number"===t?this.castValueToInteger(e.argument):"LiteralInteger"===t?this.castLiteralToInteger(e.argument):this.coerce(this.expression(e.argument),"i32");break;case"Boolean":this.emitCondition(e.argument);break;default:throw this.astErrorOutput(`unhandled return type ${this.returnType}`,e)}this.em.return_()}stmtRootReturn(e,t){const r=this.assembler?this.assembler.globals:{dataIndex:0},n=this.assembler?this.assembler.layout.outputOffset:0;switch(this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const t=parseInt(this.returnType.substring(6),10),s=e.argument;if("ArrayExpression"===s.type){if(s.elements.length!==t)throw this.astErrorOutput(`expected ${t} array elements to match return type ${this.returnType}`,e);for(let e=0;e1&&(t=!1);for(let e=0;e{if(e===a.length)return o&&this.emitSwitchConsequent(o),!1;const{tests:t,consequent:r}=a[e];for(let e=0;e0&&this.em.i32Or();return this.enterIf(),this.emitSwitchConsequent(r),(e+10&&(r.push({tests:n,consequent:e[s].consequent}),n=[])):t=e[s].consequent;return{groups:r,defaultConsequent:t}}collectSwitchCaseStatements(e){const t=[];for(let r=0;r{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(r);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t]))return!0;return!1};for(let e=0;e{const r=this.getType(t);switch(n){case"Number":case"Float":"Integer"===r?this.castValueToFloat(t):"LiteralInteger"===r?this.castLiteralToFloat(t):this.coerce(this.expression(t),"f32");break;case"Integer":"Number"===r||"Float"===r?this.castValueToInteger(t):"LiteralInteger"===r?this.castLiteralToInteger(t):this.coerce(this.expression(t),"i32");break;case"Boolean":this.emitCondition(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${n}`,e)}};return this.emitCondition(e.test),this.enterIf(s),i(e.consequent),this.em.else_(),i(e.alternate),this.exit(),"Boolean"===n?"bool":s}exprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const r=this.isAstMathFunction(e);if(t=r||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);if(this.calledFunctions.indexOf(t)<0&&this.calledFunctions.push(t),this.onFunctionCall&&this.onFunctionCall(this.name,t,e.arguments),r)return this.emitMathCall(t,e);const n=this.getType(e),s=this.lookupFunctionArgumentTypes(t)||[];for(let r=0;r{switch(this.getType(e)){case"Integer":this.castValueToFloat(e);break;case"LiteralInteger":this.castLiteralToFloat(e);break;default:this.coerce(this.expression(e),"f32")}},n=u[e];if(n)return r(t.arguments[0]),this.em[n](),"f32";switch(e){case"round":return r(t.arguments[0]),this.em.f32Const(.5).f32Add().f32Floor(),"f32";case"fround":return r(t.arguments[0]),"f32";case"min":case"max":{const n="min"===e?"f32Min":"f32Max";r(t.arguments[0]);for(let e=1;e0&&this.emitClampScalarIndex(a.dims[0]*a.dims[1]*a.dims[2]-1),this.em.i32Const(2).i32Shl(),this.em.f32Load(a.offset),"f32"}emitClampScalarIndex(e){const t=this.em.addLocal("i32");this.em.localSet(t),this.em.localGet(t).i32Const(0).localGet(t).i32Const(0).i32GeS().select(),this.em.localSet(t),this.em.localGet(t).i32Const(e).localGet(t).i32Const(e).i32LeS().select()}emitVecIndex(e,t){if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return this.em.localGet(e.indices[t.value]),"f32"}const r=this.em.addLocal("i32");this.emitIndex(t),this.em.localSet(r),this.em.localGet(e.indices[0]);for(let t=1;t{if(!e||"object"!=typeof e)return!1;switch(e.type){case"Literal":case"ThisExpression":return!1;case"Identifier":return t.has(e.name);case"MemberExpression":return e.computed||"MemberExpression"!==e.object.type||e.object.computed||!e.object.property||"thread"!==e.object.property.name?e.computed?a(e.object)||a(e.property):a(e.object):"x"===e.property.name;case"BinaryExpression":case"LogicalExpression":return a(e.left)||a(e.right);case"UnaryExpression":case"UpdateExpression":return a(e.argument);case"ConditionalExpression":return a(e.test)||a(e.consequent)||a(e.alternate);case"CallExpression":return!i.isAstMathFunction(e)||("random"===e.callee.property.name||e.arguments.some(a));case"SequenceExpression":return e.expressions.some(a);case"ArrayExpression":return e.elements.some(a);case"AssignmentExpression":return a(e.right)||"Identifier"===e.left.type&&t.has(e.left.name);default:return!0}},o=e=>{e&&!t.has(e)&&(t.add(e),s=!0)},u=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>u(e,t));switch(e.type){case"UpdateExpression":return"Identifier"===e.argument.type&&(-1!==i.argumentNames.indexOf(e.argument.name)&&(r.has(e.argument.name)||(r.add(e.argument.name),s=!0),o(e.argument.name)),t&&o(e.argument.name)),u(e.argument,t);case"AssignmentExpression":return"Identifier"===e.left.type&&(-1!==i.argumentNames.indexOf(e.left.name)&&(r.has(e.left.name)||(r.add(e.left.name),s=!0),o(e.left.name)),t&&o(e.left.name)),u(e.left,t),u(e.right,t);case"ConditionalExpression":{u(e.test,t);const r=t||a(e.test);return u(e.consequent,r),u(e.alternate,r)}case"LogicalExpression":return u(e.left,t),u(e.right,!0);default:for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const n=e[r];n&&"object"==typeof n&&u(n,t)}}}},l=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>l(e,t));switch(e.type){case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.push(e.id.name);break;case"AssignmentExpression":"Identifier"===e.left.type&&t.push(e.left.name);break;case"UpdateExpression":"Identifier"===e.argument.type&&t.push(e.argument.name);break;case"FunctionDeclaration":return}for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const n=e[r];n&&"object"==typeof n&&l(n,t)}}},h=(e,t)=>{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>h(e,t));switch(e.type){case"BreakStatement":case"ContinueStatement":return t;case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return!1;case"IfStatement":{const r=t||a(e.test);return!!h(e.consequent,r)||!!e.alternate&&h(e.alternate,r)}case"ConditionalExpression":{const r=t||a(e.test);return h(e.consequent,r)||h(e.alternate,r)}case"SwitchStatement":{const r=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));return e.cases.some(e=>e.consequent.some(e=>"BreakStatement"!==e.type&&h(e,r)))}default:for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const n=e[r];if(n&&"object"==typeof n&&h(n,t))return!0}return!1}},c=(e,n)=>{switch(e.type){case"AssignmentExpression":if("Identifier"===e.left.type){const u=e.left.name;-1!==i.argumentNames.indexOf(u)&&(r.has(u)||(r.add(u),s=!0),o(u)),(n||a(e.right)||"="!==e.operator&&t.has(u))&&o(u)}return u(e.right,n);case"UpdateExpression":if("Identifier"===e.argument.type){const t=e.argument.name;-1!==i.argumentNames.indexOf(t)&&(r.has(t)||(r.add(t),s=!0),o(t)),n&&o(t)}return;case"SequenceExpression":return e.expressions.forEach(e=>c(e,n));default:return u(e,n)}},p=(e,t)=>{if(e)switch(e.type){case"VariableDeclaration":for(const r of e.declarations)r.init&&((t||a(r.init))&&o(r.id.name),u(r.init,t));return;case"ExpressionStatement":return c(e.expression,t);case"ReturnStatement":return t&&(n=!0),void(e.argument&&u(e.argument,t));case"IfStatement":{u(e.test,t);const r=t||a(e.test);return p(e.consequent,r),void(e.alternate&&p(e.alternate,r))}case"ForStatement":case"WhileStatement":case"DoWhileStatement":{const r=t||!!e.test&&a(e.test)||h(e.body,!1);if(r){const t=[];e.init&&l(e.init,t),l(e.body,t),e.update&&l(e.update,t),t.forEach(o)}return e.init&&("VariableDeclaration"===e.init.type?p(e.init,t):c(e.init,t)),p(e.body,r),e.update&&c(e.update,r),void(e.test&&u(e.test,r))}case"SwitchStatement":{const r=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));for(const t of e.cases)for(const e of t.consequent)p(e,r);return}case"BlockStatement":return e.body.forEach(e=>p(e,t));default:return}};for(;s;)s=!1,p(e.body,!1);return{varying:t,varyingReturn:n,assignedArgs:r,exprVarying:a,hasVaryingExit:h}}vZero(){return this.em.v128ConstI32x4(0,0,0,0),this}vInnermostVaryingLoop(){const e=this.vLoopStack[this.vLoopStack.length-1];return e&&e.varying?e:null}vRecomputeCur(e){const t=this.em;t.localGet(e),-1!==this.vRetMask&&t.localGet(this.vRetMask).v128Andnot();const r=this.vInnermostVaryingLoop();r&&(-1!==r.vBrk&&t.localGet(r.vBrk).v128Andnot(),-1!==r.vCnt&&t.localGet(r.vCnt).v128Andnot()),t.localSet(this.vCur)}vLoopBodyExits(e){let t=!1,r=!1;const n=e=>{if(!(!e||"object"!=typeof e||t&&r)){if(Array.isArray(e))return e.forEach(n);switch(e.type){case"BreakStatement":return void(t=!0);case"ContinueStatement":return void(r=!0);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return;case"SwitchStatement":for(const t of e.cases)for(const e of t.consequent)"BreakStatement"!==e.type&&n(e);return}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const r=e[t];r&&"object"==typeof r&&n(r)}}};return n(e),{hasBreak:t,hasContinue:r}}vSetLocal(e){const t=this.em;this.vMaskDepth>0&&t.localGet(e).localGet(this.vCur).v128Bitselect(),t.localSet(e)}vCoerce(e,t){if(e===t)return t;const r=this.em;switch(e){case"f32":case"i32":case"bool":if("vf32"===t)return this.coerce(e,"f32"),r.f32x4Splat(),t;if("vi32"===t)return this.coerce(e,"i32"),r.i32x4Splat(),t;if("vbool"===t)return this.coerce(e,"i32"),r.i32x4Splat(),this.vZero(),r.i32x4Ne(),t;break;case"vf32":if("vi32"===t)return r.i32x4TruncSatF32x4S(),t;if("vbool"===t)return r.v128ConstF32x4(0,0,0,0).f32x4Ne(),t;break;case"vi32":if("vf32"===t)return r.f32x4ConvertI32x4S(),t;if("vbool"===t)return this.vZero(),r.i32x4Ne(),t;break;case"vbool":if("vi32"===t)return r.v128ConstI32x4(1,1,1,1).v128And(),t;if("vf32"===t)return r.v128ConstI32x4(1,1,1,1).v128And().f32x4ConvertI32x4S(),t}throw new Error(`cannot convert ${e} to ${t}`)}vCastLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastLiteralToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vCastValueToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastValueToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vEmitByType(e,t){const r=this.getType(e);return"vf32"===t?"Integer"===r?this.vCastValueToFloat(e):"LiteralInteger"===r?this.vCastLiteralToFloat(e):(this.vCoerce(this.vexpr(e),"vf32"),"vf32"):"Number"===r||"Float"===r?this.vCastValueToInteger(e):"LiteralInteger"===r?this.vCastLiteralToInteger(e):(this.vCoerce(this.vexpr(e),"vi32"),"vi32")}vexprMask(e){const t=this.vexpr(e);if("vbool"!==t)return"vi32"===t?(this.vZero(),void this.em.i32x4Ne()):void("vf32"!==t?(this.coerce(t,"bool"),this.em.i32x4Splat(),this.vZero(),this.em.i32x4Ne()):this.em.v128ConstF32x4(0,0,0,0).f32x4Ne())}vstatement(e){switch(e.type){case"VariableDeclaration":return this.vstmtVariableDeclaration(e);case"ExpressionStatement":return this.vstatementExpression(e.expression);case"ReturnStatement":return this.vstmtReturn(e);case"IfStatement":return this.vstmtIf(e);case"ForStatement":return this.vstmtFor(e);case"WhileStatement":return this.vstmtWhile(e);case"DoWhileStatement":return this.vstmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.vCastValueToFloat(n));switch(i.valueType=o,o){case"Number":case"Float":this.vSetVaryingScalar(s,"vf32",o,()=>{"LiteralInteger"===a?this.vCastLiteralToFloat(n):"Integer"===a?this.vCastValueToFloat(n):this.vCoerce(this.vexpr(n),"vf32")});break;case"Integer":this.vSetVaryingScalar(s,"vi32","Integer",()=>{"LiteralInteger"===a?this.vCastLiteralToInteger(n):"Number"===a||"Float"===a?this.vCastValueToInteger(n):this.vCoerce(this.vexpr(n),"vi32")});break;case"Boolean":this.vSetVaryingScalar(s,"vi32","Boolean",()=>{this.vexprMask(n),this.em.v128ConstI32x4(1,1,1,1).v128And()});break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${o}`,t)}}vSetVaryingScalar(e,t,r,n){let s=this.locals.get(e);s&&"vscalar"===s.kind&&s.wtype===t?s.gtype=r:(s={kind:"vscalar",index:this.em.addLocal("v128"),wtype:t,gtype:r},this.locals.set(e,s)),n(),this.vSetLocal(s.index)}vEmitArrayElement(e){switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}}vAssign(e){if("Identifier"!==e.left.type)throw this.astErrorOutput(`WebAssembly backend does not yet support assignment to ${e.left.type}`,e);const t=e.left.name,r=this.locals.get(t);if(r&&"scalar"===r.kind)return this.emitAssignment(e);if(!r||"vscalar"!==r.kind)throw this.astErrorOutput(`cannot assign to "${t}"`,e);const n=r.wtype;if("="===e.operator){const t=this.getType(e.left),r=this.getType(e.right);"Integer"!==t&&"Integer"===r?(this.vCastValueToFloat(e.right),this.vCoerce("vf32",n)):"Integer"!==t&&"LiteralInteger"===r?(this.vCastLiteralToFloat(e.right),this.vCoerce("vf32",n)):"Integer"===t&&"LiteralInteger"===r?(this.vCastLiteralToInteger(e.right),this.vCoerce("vi32",n)):"Integer"!==t||"Number"!==r&&"Float"!==r?this.vCoerce(this.vexpr(e.right),n):(this.vCastValueToInteger(e.right),this.vCoerce("vi32",n))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.vCoerce(this.vexprBinary(t),n)}this.vSetLocal(r.index)}vUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const r=this.locals.get(e.argument.name);if(r&&"scalar"===r.kind)return this.emitUpdate(e,t);if(!r||"vscalar"!==r.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const n=this.em,s="vi32"===r.wtype,i=()=>s?n.v128ConstI32x4(1,1,1,1):n.v128ConstF32x4(1,1,1,1),a="++"===e.operator?s?"i32x4Add":"f32x4Add":s?"i32x4Sub":"f32x4Sub";if(t)return n.localGet(r.index),i(),n[a](),this.vSetLocal(r.index),"void";if(e.prefix)n.localGet(r.index),i(),n[a](),this.vSetLocal(r.index),n.localGet(r.index);else{const e=n.addLocal("v128");n.localGet(r.index).localSet(e),n.localGet(r.index),i(),n[a](),this.vSetLocal(r.index),n.localGet(e)}return r.wtype}vstmtIf(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementBody(e.consequent),e.alternate&&(t.else_(),this.vstatementBody(e.alternate)),void this.exit();const r=t.addLocal("v128");this.vexprMask(e.test),t.localSet(r);const n=t.addLocal("v128");t.localGet(this.vCur).localSet(n),t.localGet(n).localGet(r).v128And().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.consequent),this.vMaskDepth--,this.exit(),e.alternate&&(t.localGet(n).localGet(r).v128Andnot().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.alternate),this.vMaskDepth--,this.exit()),this.vRecomputeCur(n)}vstmtReturn(e){const t=this.em;if(!e.argument)return void this.vRetireOrReturn();this.pushState("skip-literal-correction");const r=this.getType(e.argument);switch(this.popState("skip-literal-correction"),this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const r=parseInt(this.returnType.substring(6),10),n=e.argument,s=[];if("ArrayExpression"===n.type){if(n.elements.length!==r)throw this.astErrorOutput(`expected ${r} array elements to match return type ${this.returnType}`,e);for(let e=0;e0?i=this.vCur:-1!==this.vRetMask&&(i=t.addLocal("v128"),t.localGet(this.vRetMask).v128Not().localSet(i));const a=t.addLocal("i32");if(1===s)return t.globalGet(r.dataIndex).i32Const(2).i32Shl().localSet(a),void(-1===i?t.localGet(a).localGet(e[0]).v128Store(n,2):(t.localGet(a),t.localGet(e[0]),t.localGet(a).v128Load(n,2),t.localGet(i).v128Bitselect(),t.v128Store(n,2)));t.globalGet(r.dataIndex).i32Const(s).i32Mul().i32Const(2).i32Shl().localSet(a);for(let r=0;r<4;r++)for(let o=0;oe.test&&this.vInfo.exprVarying(e.test)),i=this.getType(t);if(!s){let s,a;switch(i){case"Float":case"Number":a=!1,s=n.addLocal("f32"),this.coerce(this.expression(t),"f32"),n.localSet(s);break;case"Integer":a=!0,s=n.addLocal("i32"),this.coerce(this.expression(t),"i32"),n.localSet(s);break;default:throw this.astErrorOutput(`Unhandled switch discriminant type "${i}"`,e)}if(1===r.length&&!r[0].test)return void this.vEmitSwitchConsequent(r[0].consequent);const{groups:o,defaultConsequent:u}=this.collectSwitchGroups(r),l=e=>{if(e===o.length)return void(u&&this.vEmitSwitchConsequent(u));const{tests:t,consequent:r}=o[e];for(let e=0;e0&&n.i32Or();this.enterIf(),this.vEmitSwitchConsequent(r),(e+10&&n.v128Or();n.localSet(p),this.vRecomputeCur(h),n.localGet(this.vCur).localGet(p).v128And().localGet(c).v128Andnot().localSet(this.vCur),n.localGet(c).localGet(p).v128Or().localSet(c),n.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(r),this.exit()}l&&(this.vRecomputeCur(h),n.localGet(this.vCur).localGet(c).v128Andnot().localSet(this.vCur),n.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(l),this.exit()),this.vMaskDepth--,this.vRecomputeCur(h)}vEmitSwitchTest(e,t){const r=this.getType(e);t?"Number"===r||"Float"===r?this.vCastValueToInteger(e):"LiteralInteger"===r?this.vCastLiteralToInteger(e):this.vCoerce(this.vexpr(e),"vi32"):"LiteralInteger"===r?this.vCastLiteralToFloat(e):"Integer"===r?this.vCastValueToFloat(e):this.vCoerce(this.vexpr(e),"vf32")}vEmitSwitchConsequent(e){const t=this.collectSwitchCaseStatements(e),r=this.vTerminated;this.vTerminated=!1;for(let e=0;e{const r=this.getType(t);switch(s){case"Number":case"Float":"Integer"===r?this.vCastValueToFloat(t):"LiteralInteger"===r?this.vCastLiteralToFloat(t):this.vCoerce(this.vexpr(t),"vf32");break;case"Integer":"Number"===r||"Float"===r?this.vCastValueToInteger(t):"LiteralInteger"===r?this.vCastLiteralToInteger(t):this.vCoerce(this.vexpr(t),"vi32");break;case"Boolean":this.vexprMask(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${s}`,e)}},a="Integer"===s?"vi32":"Boolean"===s?"vbool":"vf32";if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf("v128"),i(e.consequent),t.else_(),i(e.alternate),this.exit(),a;const o=t.addLocal("v128");this.vexprMask(e.test),t.localSet(o);const u=t.addLocal("v128");t.localGet(this.vCur).localSet(u);const l=t.addLocal("v128"),h=t.addLocal("v128");return t.localGet(u).localGet(o).v128And().localSet(this.vCur),this.vMaskDepth++,i(e.consequent),t.localSet(l),t.localGet(u).localGet(o).v128Andnot().localSet(this.vCur),i(e.alternate),t.localSet(h),this.vMaskDepth--,t.localGet(u).localSet(this.vCur),t.localGet(l).localGet(h).localGet(o).v128Bitselect(),a}vTernaryStatement(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementExpression(e.consequent),t.else_(),this.vstatementExpression(e.alternate),void this.exit();const r=t.addLocal("v128");this.vexprMask(e.test),t.localSet(r);const n=t.addLocal("v128");t.localGet(this.vCur).localSet(n),t.localGet(n).localGet(r).v128And().localSet(this.vCur),this.vMaskDepth++,this.vstatementExpression(e.consequent),t.localGet(n).localGet(r).v128Andnot().localSet(this.vCur),this.vstatementExpression(e.alternate),this.vMaskDepth--,t.localGet(n).localSet(this.vCur)}vexprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const r=this.isAstMathFunction(e);if(t=r||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);return r?this.vMathCall(t,e):this.vUserCall(t,e)}vUserCall(e,t){const r=this.em,n=this.assembler.helperInfo||{readsThread:!1,usesRandom:!1},s=this.assembler.globals,i=this.getType(t),a=this.lookupFunctionArgumentTypes(e)||[],o=[];for(let n=0;n0&&r.i32Const(t).i32Add(),r.globalSet(s.threadX)),n.usesRandom&&r.localGet(c).i32x4ExtractLane(t).globalSet(s.pcgState);for(const e of o)r.localGet(e.index),"vi32"===e.wtype?r.i32x4ExtractLane(t):r.f32x4ExtractLane(t);r.call(this.mangleFunctionName(e)),"void"!==u&&r.localSet(l),n.usesRandom&&r.localGet(c).globalGet(s.pcgState).i32x4ReplaceLane(t).localSet(c),"void"!==u&&(0===t?(r.localGet(l),"i32"===u?r.i32x4Splat():r.f32x4Splat(),r.localSet(h)):(r.localGet(h).localGet(l),"i32"===u?r.i32x4ReplaceLane(t):r.f32x4ReplaceLane(t),r.localSet(h)))}return n.readsThread&&r.localGet(this._vBaseX).globalSet(s.threadX),n.usesRandom&&(r.localGet(c).globalGet(s.pcgStateV),this.vMaskDepth>0?r.localGet(this.vCur):r.v128ConstI32x4(-1,-1,-1,-1),r.v128Bitselect().globalSet(s.pcgStateV)),"void"===u?"void":(r.localGet(h),"i32"===u?"vi32":"vf32")}vMathCall(e,t){const r=this.em;if("random"===e)return this.usesRandom=!0,this.vMaskDepth>0?r.localGet(this.vCur):r.v128ConstI32x4(-1,-1,-1,-1),r.call("pcg_random_v"),"vf32";const n=e=>{switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}},s=v[e];if(s)return n(t.arguments[0]),r[s](),"vf32";switch(e){case"round":return n(t.arguments[0]),r.v128ConstF32x4(.5,.5,.5,.5).f32x4Add().f32x4Floor(),"vf32";case"fround":return n(t.arguments[0]),"vf32";case"min":case"max":{const s="min"===e?"f32x4Min":"f32x4Max";n(t.arguments[0]);for(let e=1;e{r.localGet(e.indices[t]),"vec"===e.kind&&r.f32x4Splat()};if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return n(t.value),"vf32"}const s=r.addLocal("v128");this.vEmitIndex(t),r.localSet(s);const i=r.addLocal("v128");n(0),r.localSet(i);for(let t=1;tthis.isThreadDependent(e));switch(e.type){case"MemberExpression":{const t=this.getVariableSignature(e);if("this.thread.value"===t||"value.thread.value"===t)return"x"===e.property.name;break}case"CallExpression":if(this.isAstMathFunction(e)){if("random"===e.callee.property.name)return!0;break}return!0;case"Identifier":return!!this.taintedLocals&&this.taintedLocals.has(e.name);case"ThisExpression":return!1}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const r=e[t];if(r&&"object"==typeof r&&this.isThreadDependent(r))return!0}return!1}recordUniformity(e,t){this._analysisPass&&this.uniformity.push({kind:e,threadDependent:!t||this.isThreadDependent(t)})}}}}),ot=e((e,t)=>{let n=null;try{n=r()}catch(e){}const s="function"==typeof Worker;const i="\nvar entries = {};\nvar pipelines = {};\nfunction handleMessage(message, post) {\n if (message.type === 'setup') {\n var imports = { env: { memory: message.memory } };\n for (var i = 0; i < message.mathImports.length; i++) {\n imports.env['math_' + message.mathImports[i]] = Math[message.mathImports[i]];\n }\n var instance = new WebAssembly.Instance(message.module, imports);\n entries[message.id] = {\n run: instance.exports.run,\n runSimd: instance.exports.run_simd || null,\n sizeX: message.sizeX\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'pipelineSetup') {\n var instances = [];\n for (var i = 0; i < message.modules.length; i++) {\n var imports = { env: { memory: message.memory } };\n var math = message.moduleMathImports[i];\n for (var j = 0; j < math.length; j++) {\n imports.env['math_' + math[j]] = Math[math[j]];\n }\n instances.push(new WebAssembly.Instance(message.modules[i], imports));\n }\n var steps = [];\n for (var i = 0; i < message.steps.length; i++) {\n var exported = instances[message.steps[i].module].exports;\n steps.push({\n run: exported.run,\n runSimd: exported.run_simd || null,\n sizeX: message.steps[i].sizeX\n });\n }\n pipelines[message.id] = {\n steps: steps,\n i32: new Int32Array(message.memory.buffer),\n countIndex: message.countIndex,\n genIndex: message.genIndex,\n abortIndex: message.abortIndex\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'release') {\n delete entries[message.id];\n delete pipelines[message.id];\n } else if (message.type === 'run') {\n var entry = entries[message.id];\n var start = message.start;\n var end = message.end;\n var seed = message.seed;\n if (entry.runSimd && (entry.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) entry.runSimd(start, quadEnd, seed);\n if (quadEnd < end) entry.run(quadEnd, end, seed);\n } else {\n entry.run(start, end, seed);\n }\n post({ type: 'done', taskId: message.taskId });\n } else if (message.type === 'pipelineRun') {\n var pipeline = pipelines[message.id];\n var i32 = pipeline.i32;\n var gen = message.baseGen;\n var aborted = false;\n for (var s = 0; s < pipeline.steps.length && !aborted; s++) {\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n var step = pipeline.steps[s];\n var start = message.ranges[s * 2];\n var end = message.ranges[s * 2 + 1];\n var seed = message.seeds[s];\n if (end > start) {\n if (step.runSimd && (step.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) step.runSimd(start, quadEnd, seed);\n if (quadEnd < end) step.run(quadEnd, end, seed);\n } else {\n step.run(start, end, seed);\n }\n }\n gen++;\n if (Atomics.add(i32, pipeline.countIndex, 1) + 1 === message.workerCount) {\n Atomics.store(i32, pipeline.countIndex, 0);\n Atomics.store(i32, pipeline.genIndex, gen);\n Atomics.notify(i32, pipeline.genIndex);\n } else {\n for (;;) {\n if (Atomics.load(i32, pipeline.genIndex) >= gen) break;\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n Atomics.wait(i32, pipeline.genIndex, gen - 1, 100);\n }\n }\n }\n post({ type: 'done', taskId: message.taskId, aborted: aborted });\n }\n}\nif (typeof self !== 'undefined' && typeof postMessage === 'function') {\n self.onmessage = function(event) {\n handleMessage(event.data, function(message) { postMessage(message); });\n };\n} else {\n var parentPort = require('worker_threads').parentPort;\n parentPort.on('message', function(message) {\n handleMessage(message, function(reply) { parentPort.postMessage(reply); });\n });\n}\n";t.exports={WebAssemblyWorkerPool:class{constructor(e){this.size=e||function(){if("undefined"!=typeof navigator&&navigator.hardwareConcurrency)return navigator.hardwareConcurrency;if(n&&"function"==typeof n.cpus){const e=n.cpus().length;if(e)return e}return 4}(),this.workers=[],this.destroyed=!1,this.dispatchCount=0,this.lastDispatch=null,this._taskId=0}get liveWorkerCount(){let e=0;for(const t of this.workers)t.dead||e++;return e}_spawn(){const e={handle:null,dead:!1,state:{setup:new Set,settingUp:new Map,pending:new Map},fail:null,die:null},t=e.state;e.fail=e=>{for(const r of t.settingUp.values())r.reject(e);t.settingUp.clear();for(const r of t.pending.values())r.reject(e);t.pending.clear()},e.die=t=>{if(!e.dead&&(e.dead=!0,e.fail(t),e.handle&&"function"==typeof e.handle.terminate))try{e.handle.terminate()}catch(e){}};const n=r=>{if("ready"===r.type){const n=t.settingUp.get(r.id);n&&(t.settingUp.delete(r.id),t.setup.add(r.id),this._updateRef(e),n.resolve())}else if("done"===r.type){const n=t.pending.get(r.taskId);n&&(t.pending.delete(r.taskId),this._updateRef(e),n.resolve())}};let a;if(s){const t=URL.createObjectURL(new Blob([i],{type:"text/javascript"}));a=new Worker(t),URL.revokeObjectURL(t),a.onmessage=e=>n(e.data),a.onerror=t=>e.die(new Error(t.message||"WebAssembly worker error"))}else{const{Worker:t}=r();a=new t(i,{eval:!0}),a.on("message",n),a.on("error",t=>e.die(t)),a.on("exit",t=>{e.die(new Error(`WebAssembly worker exited with code ${t}`))}),a.unref()}return e.handle=a,e}_worker(e){for(;this.workers.length<=e;)this.workers.push(this._spawn());return this.workers[e].dead&&(this.workers[e]=this._spawn()),this.workers[e]}_updateRef(e){!e.dead&&e.handle&&"function"==typeof e.handle.ref&&(e.state.settingUp.size+e.state.pending.size>0?e.handle.ref():e.handle.unref())}_ensureSetup(e,t){if(e.state.setup.has(t.id))return Promise.resolve();let r=e.state.settingUp.get(t.id);return r||(r={},r.promise=new Promise((e,t)=>{r.resolve=e,r.reject=t}),e.state.settingUp.set(t.id,r),this._updateRef(e),e.handle.postMessage(t.pipeline?{type:"pipelineSetup",id:t.id,memory:t.memory,modules:t.modules,moduleMathImports:t.moduleMathImports,steps:t.steps,countIndex:t.countIndex,genIndex:t.genIndex,abortIndex:t.abortIndex}:{type:"setup",id:t.id,module:t.module,memory:t.memory,mathImports:t.mathImports,sizeX:t.sizeX})),r.promise}dispatch(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:t.length,ranges:t.map(e=>[e.start,e.end])};const r=t.map((t,r)=>{const n=this._worker(r);return this._ensureSetup(n,e).then(()=>new Promise((r,s)=>{if(n.dead)return void s(new Error("WebAssembly worker died before the task could run"));const i=++this._taskId;n.state.pending.set(i,{resolve:r,reject:s}),this._updateRef(n),n.handle.postMessage({type:"run",id:e.id,taskId:i,start:t.start,end:t.end,seed:t.seed})}))});return Promise.all(r).then(()=>{})}dispatchPipeline(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:e.workerCount,ranges:e.workerRanges.map(e=>e.slice())};const r=[];for(let n=0;nnew Promise((r,i)=>{if(s.dead)return void i(new Error("WebAssembly worker died before the task could run"));const a=++this._taskId;s.state.pending.set(a,{resolve:r,reject:i}),this._updateRef(s),s.handle.postMessage({type:"pipelineRun",id:e.id,taskId:a,ranges:e.workerRanges[n],seeds:t.seeds,baseGen:t.baseGen,workerCount:e.workerCount})})))}return Promise.all(r).then(()=>{})}release(e){if(!this.destroyed)for(const t of this.workers){if(t.dead)continue;t.state.setup.delete(e);const r=t.state.settingUp.get(e);r&&(t.state.settingUp.delete(e),r.reject(new Error("WebAssembly kernel entry released during setup")),this._updateRef(t)),t.handle.postMessage({type:"release",id:e})}}destroy(){if(this.destroyed)return;this.destroyed=!0;const e=new Error("WebAssembly worker pool has been destroyed");for(const t of this.workers)t.dead=!0,t.fail(e),t.handle.terminate();this.workers=[]}}}}),ut=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:s}=o(),{WebAssemblyFunctionNode:u}=at(),{WasmModuleBuilder:l}=it(),{WebAssemblyWorkerPool:h}=ot(),{utils:c}=i(),{Input:p}=n(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0});let f=null,m=null,g=1;t.exports={WebAssemblyKernel:class e extends r{static get isSupported(){return"object"==typeof WebAssembly&&null!==WebAssembly&&WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0]))}static get isSIMDSupported(){if(null===f)try{const e=new l;e.addFunction("t",{params:[],results:[]}).v128ConstI32x4(0,0,0,0).drop(),f=WebAssembly.validate(e.toBytes())}catch(e){f=!1}return f}static get isThreadsSupported(){if(null===m)try{if("undefined"==typeof SharedArrayBuffer)m=!1;else{const e=new l;e.addMemoryImport(1,1,!0);const t=new WebAssembly.Memory({initial:1,maximum:1,shared:!0});new WebAssembly.Instance(new WebAssembly.Module(e.toBytes()),{env:{memory:t}}),m=!0}}catch(e){m=!1}return m}static isContextMatch(e){return!1}static getFeatures(){return d}static get features(){return d}static get mode(){return"webasm"}static getSignature(e,t){return"webasm"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static dispatchSpans(e,t,r,n,s){if(!t||0===r)return e(0,r,s),"scalar";if(!(3&n))return t(0,r,s),"simd";const i=-4&n,a=r/n;for(let r=0;r0&&t(a,a+i,s),e(a+i,a+n,s)}return i>0?"simd+scalar-tail":"scalar"}static nativeFunctionArguments(){throw new Error("WebAssembly backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebAssembly backend does not yet support native functions")}static combineKernels(){throw new Error("WebAssembly backend does not yet support combineKernels")}constructor(e,t){super(e,t),this.poolSize=null,this.mergeSettings(e.settings||t),null===this.precision&&(this.precision="single"),this.threadDim=null,this.componentCount=1,this.moduleCacheLimit=8,this.functionBuilder=null,this.tracedFunctions=null,this.usesRandom=!1,this.usedMathImports=null,this._moduleCache=new Map,this._active=null,this._lastRunPath=null,this._pool=null,this._threadedTail=Promise.resolve(),this._threadedBusy=0,this._threadedEpoch=0}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built&&!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");return this.output=t,this}toString(){throw new Error("WebAssembly backend does not yet support toString")}build(){if(this.built)return;if(this.gpu&&this.gpu.kernels&&-1===this.gpu.kernels.indexOf(this)&&this.gpu.kernels.push(this),this.graphical)return this.requestFallback(arguments,"graphical mode is not supported on the webasm backend");if(this.subKernels&&this.subKernels.length>0)return this.requestFallback(arguments,"kernel maps are not supported on the webasm backend");this.setupConstants(),this.setupArguments(arguments);for(let e=0;e16*Math.ceil(e/16);let r=0;const n={},s={};for(let i=0;i=4096}_entryKey(e){return this._computeSizeSignature(e)+(this._threadable()?"|shared":"")}_assembleModule(t,r,n){const s=new l,i=t.totalBytes||t.outputOffset+r*this.componentCount*4,a=Math.ceil(i/65536)+16,o=Math.max(a,4096);s.addMemoryImport(a,o,n);const u=Array.from(this.usedMathImports).sort();for(const e of u){const t="pow"===e||"atan2"===e?["f32","f32"]:["f32"];s.addFuncImport("math_"+e,t,["f32"])}const h={threadX:s.addGlobal("i32",!0,0),threadY:s.addGlobal("i32",!0,0),threadZ:s.addGlobal("i32",!0,0),dataIndex:s.addGlobal("i32",!0,0)};this.usesRandom&&(h.pcgState=s.addGlobal("i32",!0,0),this._emitPcgRandom(s,h.pcgState));const c={module:s,layout:t,globals:h};for(let e=this.tracedFunctions.length-1;e>=0;e--){const t=this.tracedFunctions[e];if("kernel"===t)continue;const r=this.functionBuilder.functionMap[t];r&&(r.output=this.output,r.emitFunction(c))}this.functionBuilder.functionMap.kernel.output=this.output,this.functionBuilder.functionMap.kernel.emitFunction(c);const[p,d]=this.threadDim,f=s.addFunction("run",{params:["i32","i32","i32"],locals:["i32"]});if(f.localGet(0).localSet(3),1===this.output.length?(f.i32Const(0).globalSet(h.threadY),f.i32Const(0).globalSet(h.threadZ)):2===this.output.length&&f.i32Const(0).globalSet(h.threadZ),f.block(),f.localGet(3).localGet(1).i32GeS().brIf(0),f.loop(),f.localGet(3).globalSet(h.dataIndex),1===this.output.length?f.localGet(3).globalSet(h.threadX):2===this.output.length?(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().globalSet(h.threadY)):(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().i32Const(d).i32RemU().globalSet(h.threadY),f.localGet(3).i32Const(p*d).i32DivU().globalSet(h.threadZ)),this.usesRandom&&f.localGet(2).localGet(3).i32Const(-1640531527).i32Mul().i32Add().i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(h.pcgState),f.call("kernel"),f.localGet(3).i32Const(1).i32Add().localSet(3),f.localGet(3).localGet(1).i32LtS().brIf(0),f.end(),f.end(),s.exportFunction("run"),e.isSIMDSupported){this.usesRandom&&(h.pcgStateV=s.addGlobal("v128",!0,0),this._emitPcgRandomVector(s,h.pcgStateV));let e=null;for(const t of this.tracedFunctions){if("kernel"===t)continue;const r=this.functionBuilder.functionMap[t];r&&(e||(e={readsThread:!1,usesRandom:!1}),r.readsThread&&(e.readsThread=!0),r.usesRandom&&(e.usesRandom=!0))}c.helperInfo=e,this.functionBuilder.functionMap.kernel.emitVectorFunction(c),this._emitRunSimd(s,h),s.exportFunction("run_simd")}return{bytes:s.toBytes(),initial:a,maximum:o}}_emitRunSimd(e,t){const[r,n]=this.threadDim,s=e.addFunction("run_simd",{params:["i32","i32","i32"],locals:["i32"]});s.localGet(0).localSet(3),1===this.output.length?(s.i32Const(0).globalSet(t.threadY),s.i32Const(0).globalSet(t.threadZ)):2===this.output.length&&s.i32Const(0).globalSet(t.threadZ),s.block(),s.localGet(3).localGet(1).i32GeS().brIf(0),s.loop(),s.localGet(3).globalSet(t.dataIndex),1===this.output.length?s.localGet(3).globalSet(t.threadX):2===this.output.length?(s.localGet(3).i32Const(r).i32RemU().globalSet(t.threadX),s.localGet(3).i32Const(r).i32DivU().globalSet(t.threadY)):(s.localGet(3).i32Const(r).i32RemU().globalSet(t.threadX),s.localGet(3).i32Const(r).i32DivU().i32Const(n).i32RemU().globalSet(t.threadY),s.localGet(3).i32Const(r*n).i32DivU().globalSet(t.threadZ)),this.usesRandom&&(s.localGet(3).i32x4Splat().v128ConstI32x4(0,1,2,3).i32x4Add(),s.v128ConstI32x4(-1640531527,-1640531527,-1640531527,-1640531527).i32x4Mul(),s.localGet(2).i32x4Splat().i32x4Add(),s.v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul(),s.v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add(),s.globalSet(t.pcgStateV)),s.call("kernel_simd"),s.localGet(3).i32Const(4).i32Add().localSet(3),s.localGet(3).localGet(1).i32LtS().brIf(0),s.end(),s.end()}_emitPcgRandomVector(e,t){const r=e.addFunction("pcg_random_v",{params:["v128"],results:["v128"]}),n=r.addLocal("v128"),s=r.addLocal("i32");r.globalGet(t).v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul().v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add().globalGet(t).localGet(0).v128Bitselect().globalSet(t),r.globalGet(t).localSet(n),r.localGet(n).i32x4ExtractLane(0).localSet(s),r.localGet(s).localGet(s).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4Splat();for(let e=1;e<4;e++)r.localGet(n).i32x4ExtractLane(e).localSet(s),r.localGet(s).localGet(s).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4ReplaceLane(e);r.localGet(n).v128Xor(),r.v128ConstI32x4(277803737,277803737,277803737,277803737).i32x4Mul();const i=r.addLocal("v128");r.localTee(i),r.i32Const(22).i32x4ShrU().localGet(i).v128Xor(),r.i32Const(8).i32x4ShrU(),r.f32x4ConvertI32x4U(),r.v128ConstF32x4(16777216,16777216,16777216,16777216).f32x4Div()}_emitPcgRandom(e,t){const r=e.addFunction("pcg_random",{params:[],results:["f32"]}),n=r.addLocal("i32");r.globalGet(t).i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(t),r.globalGet(t).globalGet(t).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().globalGet(t).i32Xor().i32Const(277803737).i32Mul().localTee(n),r.i32Const(22).i32ShrU().localGet(n).i32Xor().i32Const(8).i32ShrU().f32ConvertI32U().f32Const(16777216).f32Div()}_releaseEntry(e){const t=()=>{e.instance=null,e.module=null,e.memory=null,e.run=null,e.runSimd=null,e.f32=null,e.i32=null,e.bytes=null};if(e.shared&&this._pool){const r=this._pool;this._threadedTail.then(()=>{r.release(e.id),t()},t)}else t()}_instantiate(e,t){let r=this._moduleCache.get(e);if(r&&(this._moduleCache.delete(e),this._moduleCache.set(e,r)),!r){const n=this._threadable(),s=this.computeLayout(t),[i,a,o]=this.threadDim,u=i*a*o,{bytes:l,initial:h,maximum:d}=this._assembleModule(s,u,n);if(!WebAssembly.validate(l))throw new Error("WebAssembly backend: generated module failed validation (internal error)");const f=n?new WebAssembly.Memory({initial:h,maximum:d,shared:!0}):new WebAssembly.Memory({initial:h,maximum:d}),m={env:{memory:f}};for(const e of this.usedMathImports)m.env["math_"+e]=Math[e];const y=new WebAssembly.Module(l),x=new WebAssembly.Instance(y,m);r={id:g++,sizeSignature:e,shared:n,layout:s,cells:u,bytes:l,module:y,memory:f,mathImports:Array.from(this.usedMathImports).sort(),sizeX:i,instance:x,run:x.exports.run,runSimd:x.exports.run_simd||null,f32:new Float32Array(f.buffer),i32:new Int32Array(f.buffer)};for(const e in s.constantArrays){const t=s.constantArrays[e],n=this.constants[e];c.flattenTo(n instanceof p?n.value:n,r.f32.subarray(t.offset/4,t.offset/4+t.flatLength))}for(this._moduleCache.set(e,r);this._moduleCache.size>Math.max(this.moduleCacheLimit,1);){const e=this._moduleCache.keys().next().value,t=this._moduleCache.get(e);this._moduleCache.delete(e),this._releaseEntry(t)}}this._active=r}checkArgumentTypes(e){if(super.checkArgumentTypes(e),!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let r=0;r>>0:4294967296*Math.random()>>>0),l|=0,this._lastRunPath=e.dispatchSpans(o,u,s,t[0],l);const h=n.outputOffset/4,d=i.slice(h,h+s*this.componentCount);return this._shapeOutput(d,Array.from(this.output),this.componentCount)}_runThreaded(e){const t=this._active,{layout:r,cells:n}=t,s=0===this._threadedBusy;let i=null,a=null;if(s){for(const n in r.arrays){const s=r.arrays[n],i=e[s.index];c.flattenTo(i instanceof p?i.value:i,t.f32.subarray(s.offset/4,s.offset/4+s.flatLength))}for(const n in r.scalars){const s=r.scalars[n],i=e[s.index];"Integer"===s.type?t.i32[s.offset/4]=0|i:"Boolean"===s.type?t.i32[s.offset/4]=i?1:0:t.f32[s.offset/4]=i}}else{i=[];for(const t in r.arrays){const n=r.arrays[t],s=e[n.index],a=new Float32Array(n.flatLength);c.flattenTo(s instanceof p?s.value:s,a),i.push({record:n,flat:a})}a=[];for(const t in r.scalars){const n=r.scalars[t];a.push({record:n,value:e[n.index]})}}let o=0;this.usesRandom&&(o=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0),o|=0,this._pool||(this._pool=new h(this.poolSize||void 0));const u=this._pool,l=this.componentCount,d=Array.from(this.output);this._threadedBusy++;const f=this._threadedTail.then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");if(i){for(let e=0;e=n)break;h.push({start:r,end:t===e-1?n:Math.min(r+s,n),seed:o})}return this._lastRunPath="threaded",u.dispatch(t,h).then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");const e=r.outputOffset/4,s=t.f32.slice(e,e+n*l);return this._shapeOutput(s,d,l)})}),m=this._threadedEpoch,g=()=>{this._threadedEpoch===m&&this._threadedBusy--};return this._threadedTail=f.then(g,g),f}_shapeOutput(e,t,r){const[n,s,i]=[t[0],t[1]||1,t[2]||1];if(1===r)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,n);case 2:return c.erectMemoryOptimized2DFloat(e,n,s);default:return c.erectMemoryOptimized3DFloat(e,n,s,i)}const a=r,o=t=>{const r=new Array(n);for(let s=0;s{const{utils:r}=i(),{Input:s}=n(),{WebAssemblyKernel:a}=ut(),{WebAssemblyWorkerPool:o}=ot(),u=["Array","Input","Number","Float","Integer","Boolean"];let l=1;var h=class extends Error{constructor(e,t){super(e),this.isFusionFallback=!0,this.recompilable=Boolean(t)}};function c(e){return e&&"function"==typeof e.toArray?e.toArray():e}function p(e){const t=e instanceof s?Array.from(e.size):Array.from(r.getDimensions(e));for(;t.length<3;)t.push(1);return t}function d(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}t.exports={WebAssemblyPipelineExecutor:class e{static compile(t,r,n){for(let e=0;er.getVariableType(e,h)).join(",");let d=n.get(p);if(!d){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(o.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=o.clone.kernel;this._prepareKernel(e,l),d={id:n.size,kernel:e,constantRegions:null},n.set(p,d)}u[s]=d,c[s]=l}for(let e=0;e{const t=p;return p=(e=>16*Math.ceil(e/16))(p+e),t};let f=0,m=-1;if(!this.pipeline._threadsDisabled&&a.isThreadsSupported){let e=0;for(let r=0;re&&(e=s)}const r=new o;f=Math.min(r.size,Math.ceil(e/4096)),f>1?(this.threaded=!0,this.kind="fused-threaded",this.pool=r,m=d(12)):r.destroy()}const g=new Map,y=new Map,x=new Map,b=[],v=[],T=[],S=new Array(t.steps.length);for(let e=0;e${i}`;let l=E.get(o);if(!l){const a={arrays:s.arrays,scalars:s.scalars,constantArrays:r.constantRegions,outputOffset:i,totalBytes:_},u=w[t.steps[e].outputBuffer].cells,h=n._assembleModule(a,u,this.threaded);null===this.memory&&(this.memory=this.threaded?new WebAssembly.Memory({initial:h.initial,maximum:h.maximum,shared:!0}):new WebAssembly.Memory({initial:h.initial,maximum:h.maximum}),this.f32=new Float32Array(this.memory.buffer),this.i32=new Int32Array(this.memory.buffer));const c={env:{memory:this.memory}};for(const e of n.usedMathImports)c.env["math_"+e]=Math[e];const p=new WebAssembly.Module(h.bytes),d=new WebAssembly.Instance(p,c);l={run:d.exports.run,runSimd:d.exports.run_simd||null,moduleIndex:k.length},k.push(p),L.push(Array.from(n.usedMathImports).sort()),E.set(o,l)}I[e]={run:l.run,runSimd:l.runSimd,moduleIndex:l.moduleIndex,cells:w[t.steps[e].outputBuffer].cells,sizeX:n.threadDim[0],usesRandom:n.usesRandom,randomSeed:n.randomSeed}}if(this.threaded){const e=[];for(let r=0;r=t?(n[2*e]=0,n[2*e+1]=0):(n[2*e]=i,n[2*e+1]=r===f-1?t:Math.min(i+s,t))}e.push(n)}this._entry={id:"pipeline:"+l++,pipeline:!0,memory:this.memory,modules:k,moduleMathImports:L,steps:I.map(e=>({module:e.moduleIndex,sizeX:e.sizeX})),countIndex:m/4,genIndex:m/4+1,abortIndex:m/4+2,workerCount:f,workerRanges:e}}for(let e=0;e{const r=e.binding;if("step"===r.source){const e=r.step,n=w[t.steps[e].outputBuffer],s=u[e].kernel;return{kind:"step",base:n.offset/4,count:n.cells*s.componentCount,output:t.steps[e].output,componentCount:s.componentCount,kernel:s}}return"pipelineArg"===r.source?{kind:"arg",index:r.index}:{kind:"literal",value:r.value}}),this._stepRuns=I,this._argArrayRegions=g,this._argScalarSlots=y,this._scratch=null}_representativeArgs(e,t){const r=new Array(e.argBindings.length);for(let n=0;n>>0:4294967296*Math.random()>>>0):0}_executeThreaded(e){const t=this._entry,r=this.i32,n=this._stepRuns.map(e=>this._drawSeed(e));this._lastRunAborted&&(Atomics.store(r,t.countIndex,0),Atomics.store(r,t.abortIndex,0),this._lastRunAborted=!1,this._abortError=null);const s=Atomics.load(r,t.genIndex),i=s+this._stepRuns.length;return this.pool.dispatchPipeline(t,{baseGen:s,seeds:n}).then(null,e=>this._abort(e)),this._waitForGeneration(i).then(()=>this._readResults(e))}_waitForGeneration(e){const t=this.i32,r=this._entry.genIndex,n="function"==typeof Atomics.waitAsync?Atomics.waitAsync:null;return new Promise((s,i)=>{const a="function"==typeof setInterval?setInterval(()=>{},200):null,o=(e,t)=>{null!==a&&clearInterval(a),e(t)},u=this._entry.countIndex;let l=Atomics.load(t,r),h=Atomics.load(t,u),c=Date.now();const p=()=>{if(this._abortError)return void o(i,this._abortError);const a=Atomics.load(t,r);if(a>=e)return void o(s);const d=Atomics.load(t,u);if(a!==l||d!==h)l=a,h=d,c=Date.now();else if(Date.now()-c>=this.sanityTimeoutMs){const t=new Error(`pipeline threaded barrier stalled at generation ${a} of ${e} for ${this.sanityTimeoutMs}ms`);return this._abort(t),void o(i,t)}if(n){const e=Math.max(1,Math.min(200,this.sanityTimeoutMs)),s=n(t,r,a,e);s.async?s.value.then(p):Promise.resolve().then(p)}else setTimeout(p,1)};p()})}_abort(e){if(!this._abortError&&(this._abortError=e||new Error("pipeline threaded run aborted"),this._lastRunAborted=!0,this.i32&&this._entry&&(Atomics.store(this.i32,this._entry.abortIndex,1),Atomics.notify(this.i32,this._entry.genIndex)),this.pool&&this.pool.workers))for(const e of this.pool.workers)!e.dead&&e.state.pending.size>0&&e.die(this._abortError)}abortRuns(e){this.threaded&&this._abort(e)}_readResults(e){const t=this.f32,r=this.plan.results,n=new Array(this._resultReads.length);for(let r=0;r{const{utils:r}=i(),{Input:s}=n(),{FusionFallback:a}=lt();function o(e){return e&&"function"==typeof e.toArray?e.toArray():e}function u(e,t,r){const n=e.limits,s=Math.min(n.maxStorageBufferBindingSize,n.maxBufferSize);if(t>s)throw new a(`${r} needs ${t} bytes but this device allows ${s} per storage buffer`)}function l(e){const t=e instanceof s?Array.from(e.size):Array.from(r.getDimensions(e));for(;t.length<3;)t.push(1);return t}function h(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}function c(e){return Boolean(e)&&"object"==typeof e&&!(e instanceof s)&&("function"==typeof e.toArray||"function"==typeof e.delete)}t.exports={WebGPUPipelineExecutor:class e{static async compile(t,r,n){for(let e=0;er.getVariableType(e,h)).join(",");let p=n.get(c);if(!p){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(u.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=u.clone.kernel;await this._prepareKernel(e,l),p={id:n.size,kernel:e},n.set(c,p)}o[s]=p}this._scratch=null;for(let e=0;e{const r=e.output;let n=1;for(let e=0;e{let t=f.get(e);return void 0===t&&(t=f.size,f.set(e,t)),t},g=new Map;this._passes=new Array(t.steps.length);for(let n=0;n{const t=i.argBindings[e.index];return"literal"===t.source?"l"+t.value:"a"+t.index}).join(","),T=null!==f.randomSeedOffset&&null===d.randomSeed,S=c.id+":"+y.map(m).join(",")+">"+m(b)+":"+v+(T?"#"+n:"");let A=g.get(S);if(!A){const e=new ArrayBuffer(f.byteLength),t=new Uint32Array(e),r=new Int32Array(e),n=new Float32Array(e),s=d._computeDispatch(d.threadDim);t[0]=d.threadDim[0],t[1]=d.threadDim[1],t[2]=d.threadDim[2],t[3]=s.dispatchWidth;for(let e=0;e>>0);const u=h.createBuffer({size:f.byteLength,usage:72}),l=o.length>0||T;l||p.writeBuffer(u,0,e);const c=[{binding:0,resource:{buffer:u}}];for(let e=0;e{const r=e.binding;if("step"===r.source){const e=t.steps[r.step],n=this._planBuffers[e.outputBuffer],s=o[r.step].kernel,i=n.cells*s.componentCount*4,a={kind:"step",buffer:n.buffer,offset:y,byteLength:i,output:e.output,componentCount:s.componentCount,kernel:s};return y+=function(e){return 16*Math.ceil(e/16)}(i),a}return"pipelineArg"===r.source?{kind:"arg",index:r.index}:{kind:"literal",value:r.value}}),y>0&&(this._staging=h.createBuffer({size:y,usage:9}))}_representativeArgs(e,t){const r=new Array(e.argBindings.length);for(let n=0;n>>0),n.writeBuffer(r.paramsBuffer,0,r.mirror)}}const i=t.createCommandEncoder();for(let e=0;e{const t=this._staging.getMappedRange(),r=this._shapeResults(e,t);return this._staging.unmap(),r}):Promise.resolve(this._shapeResults(e,null))}_shapeResults(e,t){const r=this.plan.results,n=new Array(this._resultReads.length);for(let r=0;r{const{Input:r}=n(),{utils:s}=i(),a="pipeline intermediate results cannot be read during orchestration",o="a pipeline must return a handle, or an Array or plain object of handles",u="pipeline has been destroyed",l="the orchestration function must be synchronous; async functions and generators cannot be traced",h="this handle belongs to a different trace; handles do not survive re-trace or cross pipelines";var c=class{};let p=null;var d=class{constructor(e){this.gpu=e,this.steps=[],this.kernels=[],this.kernelIndexes=new Map,this.handleMeta=new WeakMap,this.held=[]}createHandle(e){const t=Object.freeze(new c),r=new Proxy(t,{get(e,t){if(t===Symbol.toPrimitive||"valueOf"===t||"toString"===t)return()=>{throw new Error("pipeline intermediate results cannot be used in arithmetic or conditions during orchestration")};throw new Error(a)},set(){throw new Error(a)},ownKeys(){throw new Error(a)},has(){throw new Error(a)},getOwnPropertyDescriptor(){throw new Error(a)}});return this.handleMeta.set(r,e),r}recordKernelCall(e,t){const r=e.kernel;if(r.gpu!==this.gpu)throw new Error("pipelines can only call kernels created by the same GPU instance");if(r.graphical)throw new Error("graphical kernels are not supported inside pipelines");if(r.subKernels&&r.subKernels.length>0)throw new Error("kernel maps are not supported inside pipelines");if(!r.output)throw new Error("kernels called inside a pipeline must have a fixed output size");let n=this.kernelIndexes.get(e);void 0===n&&(n=this.kernels.length,this.kernels.push(e),this.kernelIndexes.set(e,n));const s=new Array(t.length);for(let e=0;ef(e,t)):e}function m(e){for(let t=0;t{if(this.destroyed)throw new Error(u);if(this.plan||(this.plan=this._buildPlan(),this._executor=void 0),void 0===this._executor&&await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;if(this._dropExecutor(),e.recompilable){if(await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;this._dropExecutor(),this._degrade(e.message)}}else this._degrade(e.message)}return this._executeGeneric(this.plan,t,n)}),i=()=>{this._inFlight--,r.length>0&&m(r)};return s.then(i,i),this._tail=s.then(b,b),s}_guardAsync(e){return e&&"function"==typeof e.then?e.then(null,e=>{throw this._dropExecutor(),e}):e}setConstants(e){this.constants=Object.assign({},e||{});const t=()=>{this._releasePlan()};return this._tail=this._tail.then(t,t),this}destroy(){if(this.destroyed=!0,this.gpu&&this.gpu.pipelines){const e=this.gpu.pipelines.indexOf(this);-1!==e&&this.gpu.pipelines.splice(e,1)}this._executor&&"function"==typeof this._executor.abortRuns&&this._executor.abortRuns(new Error(u));const e=()=>{this._releasePlan()},t=this._tail.then(e,e);return this._tail=t,t}_buildPlan(){const e=new d(this.gpu),t=new Array(this.argumentCount);for(let r=0;r({key:r,binding:e.bindValue(t)}))};if(t instanceof c)throw new Error(h);if("object"==typeof t&&!ArrayBuffer.isView(t)){if("function"==typeof t.then)throw new Error(l);const r=Object.getPrototypeOf(t);if(r!==Object.prototype&&null!==r)throw new Error(o);const n=[];for(const r in t)t.hasOwnProperty(r)&&n.push({key:r,binding:e.bindValue(t[r])});if(0===n.length)throw new Error(o);return{kind:"object",entries:n}}throw new Error(o)}(e,n),i=function(e,t){const r=new Array(e.length).fill(-1);for(let t=0;te.binding)),a=e.kernels.map(e=>({shortcut:e,clone:this._cloneKernel(e)}));return{steps:e.steps,buffers:i,results:s,kernels:a,held:e.held,genericClones:new Map}}_genericClone(e,t){const r=t.argBindings.map(e=>"step"===e.source?"T":"pipelineArg"===e.source?"a"+e.index:"l").join(","),n=t.kernel+":"+t.outputBuffer+":"+r;let s=e.genericClones.get(n);return s||(s=this._cloneKernel(e.kernels[t.kernel].clone,{immutable:!1,dynamicArguments:!1}),e.genericClones.set(n,s)),s}_prepareExecutor(e){if(this._fusionDisabled)return void(this._executor=!1);const t=this.plan.kernels;if(t.length>0&&"webgpu"===t[0].clone.kernel.constructor.mode){const{WebGPUPipelineExecutor:t}=ht();return t.compile(this,this.plan,e).then(e=>{this._executor=e,this.executorKind=e.kind,this.fallbackReason=null},e=>{this._degrade(e&&e.message||"fused executor unavailable")})}try{const{WebAssemblyPipelineExecutor:t}=lt();this._executor=t.compile(this,this.plan,e),this.executorKind=this._executor.kind,this.fallbackReason=null}catch(e){this._degrade(e&&e.message||"fused executor unavailable")}}_dropExecutor(){this._executor&&this._executor.destroy(),this._executor=void 0}_degrade(e){this._executor=!1,this.executorKind="generic",this.fallbackReason=e}_cloneKernel(e,t){const r=e.kernel,n=Object.assign({output:Array.from(r.output),pipeline:!0,immutable:!0,dynamicArguments:!0},t||{}),s=["constants","constantTypes","precision","loopMaxIterations","strictIntegers","fixIntegerDivisionAccuracy","optimizeFloatMemory","tactic","functions","nativeFunctions","injectedNative","debug","randomSeed","returnType"];r.declaredArgumentTypes&&(n.argumentTypes=r.declaredArgumentTypes.slice());for(let e=0;e1?"function (v) { return v[this.thread.z][this.thread.y][this.thread.x]; }":t[1]>1?"function (v) { return v[this.thread.y][this.thread.x]; }":"function (v) { return v[this.thread.x]; }",a=t[2]>1?[t[0],t[1],t[2]]:t[1]>1?[t[0],t[1]]:[t[0]];s=this.gpu.createKernel(i,{output:a,pipeline:!0,immutable:!1}),e.genericClones.set(n,s)}return s(r)}_genericEagerUploadsPay(e){return 0!==e.kernels.length&&"gpu"===e.kernels[0].clone.kernel.constructor.mode}_eagerUploads(e,t){const n=new Array(t.length).fill(null);for(let s=0;s0?e.kernels[0].clone.kernel.constructor.mode:null,a="gpu"===i||"webgpu"===i,o=n||new Array(t.length).fill(null);if(a&&!n)for(let n=0;n{const{utils:r}=i(),{Input:s}=n(),{getActiveTrace:a}=ct();function o(e,t){if(t.kernel)return void(t.kernel=e);const n=r.allPropertiesOf(e);for(let r=0;rt.kernel[s]),t.__defineSetter__(s,e=>{t.kernel[s]=e})))}t.kernel=e}t.exports={kernelRunShortcut:function(e){function t(t){e.build.apply(e,t),e.checkArgumentTypes(t);let n=e.switchingKernels?void 0:e.run.apply(e,t);for(let s=0;e.switchingKernels;s++){if(s>=4){const t=e.resetSwitchingKernels();throw new Error(`this kernel cannot run the arguments it was given (${r(t)}); it did not settle on a kernel for them after 4 attempts. Create a separate kernel for this call's argument types.`)}const i=e.resetSwitchingKernels(),a=e.onRequestSwitchKernel(i,t,e);p.kernel=e=a,a.checkArgumentTypes(t),n=a.switchingKernels?void 0:a.run.apply(a,t),a.fallbackRequested&&(n=e.run.apply(e,t))}return n}function r(e){return e&&e.length?e.map(e=>"argumentTypeMismatch"===e.type?`argument ${e.index} is now ${e.needed}`:e.type).join(", "):"unknown reason"}function n(r){if(e.onAsyncModeUpgrade){const t=e.onAsyncModeUpgrade;e.onAsyncModeUpgrade=null;const s=l(r);return t(s,e).then(e=>(e&&p.replaceKernel(e),n(s)))}try{if(!0===e.constructor.isAsync)return e.build.apply(e,r),Promise.resolve(e.run.apply(e,r));for(let e=0;en(e));const s=t(r);return e.renderKernels?Promise.resolve(e.renderKernels()):e.renderOutput?e.renderOutputAsync?e.renderOutputAsync():Promise.resolve(e.renderOutput()):Promise.resolve(s)}catch(e){return Promise.reject(e)}}function i(e){return Boolean(e)&&"WebGPUBuffer"===e.type}function u(e){const t=l(e),r=[];for(let e=0;e{t[n]=e}))}return Promise.all(r).then(()=>t)}function l(e){const t=new Array(e.length);for(let r=0;r{try{e(c.apply(this,arguments))}catch(e){t(e)}})},p.replaceKernel=function(t){o(e=t,p)},o(e,p),p}}}),dt=e((e,r)=>{const{gpuMock:n}=t(),{utils:s}=i(),{Kernel:o}=a(),{CPUKernel:u}=p(),{HeadlessGLKernel:l}=be(),{WebGL2Kernel:h}=et(),{WebGLKernel:c}=xe(),{WebGPUKernel:d}=st(),{WebAssemblyKernel:f}=ut(),{kernelRunShortcut:m}=pt(),{Pipeline:g}=ct(),y=[l,h,c,f],x=["gpu","cpu"],b={headlessgl:l,webgl2:h,webgl:c,webgpu:d,webasm:f};let v=!0;function T(e){if(!e)return{};const t=Object.assign({},e);return e.hasOwnProperty("floatOutput")&&(s.warnDeprecated("setting","floatOutput","precision"),t.precision=e.floatOutput?"single":"unsigned"),e.hasOwnProperty("outputToTexture")&&(s.warnDeprecated("setting","outputToTexture","pipeline"),t.pipeline=Boolean(e.outputToTexture)),e.hasOwnProperty("outputImmutable")&&(s.warnDeprecated("setting","outputImmutable","immutable"),t.immutable=Boolean(e.outputImmutable)),e.hasOwnProperty("floatTextures")&&(s.warnDeprecated("setting","floatTextures","optimizeFloatMemory"),t.optimizeFloatMemory=Boolean(e.floatTextures)),t}r.exports={GPU:class e{static disableValidation(){v=!1}static enableValidation(){v=!0}static get isGPUSupported(){return y.some(e=>e.isSupported)}static get isKernelMapSupported(){return y.some(e=>e.isSupported&&e.features.kernelMap)}static get isOffscreenCanvasSupported(){return"undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas||"undefined"!=typeof importScripts}static get isWebGLSupported(){return c.isSupported}static get isWebGL2Supported(){return h.isSupported}static get isHeadlessGLSupported(){return l.isSupported}static get isWebGPUSupported(){return d.isSupported}static isWebGPUAvailable(){return d.isSupported?navigator.gpu.requestAdapter().then(e=>null!==e,()=>!1):Promise.resolve(!1)}static get isWebAssemblySupported(){return f.isSupported}static get isCanvasSupported(){return"undefined"!=typeof HTMLCanvasElement}static get isGPUHTMLImageArraySupported(){return h.isSupported}static get isSinglePrecisionSupported(){return y.some(e=>e.isSupported&&e.features.isFloatRead&&e.features.isTextureFloat)}constructor(t){if(t=t||{},this.canvas=t.canvas||null,this.context=t.context||null,this.mode=t.mode,this.Kernel=null,this._webGPUDecision=null,"async"===t.mode&&(d.isSupported?e.isWebGPUAvailable().then(e=>{this._webGPUDecision=e},()=>{this._webGPUDecision=!1}):this._webGPUDecision=!1),this.kernels=[],this.pipelines=[],this.functions=[],this.nativeFunctions=[],this.injectedNative=null,"dev"!==this.mode){if(this.chooseKernel(),t.functions)for(let e=0;er.argumentTypes[e]));const l=this;function h(e){console.warn("Falling back to CPU"+(y.fallbackReason?`: ${y.fallbackReason}`:""));const r=new u(t,{argumentTypes:y.argumentTypes,constantTypes:y.constantTypes,graphical:y.graphical,loopMaxIterations:y.loopMaxIterations,constants:y.constants,dynamicOutput:y.dynamicOutput,dynamicArgument:y.dynamicArguments,output:y.output,precision:y.precision,pipeline:y.pipeline,immutable:y.immutable,optimizeFloatMemory:y.optimizeFloatMemory,fixIntegerDivisionAccuracy:y.fixIntegerDivisionAccuracy,functions:y.functions,nativeFunctions:y.nativeFunctions,injectedNative:y.injectedNative,subKernels:y.subKernels,strictIntegers:y.strictIntegers,randomSeed:y.randomSeed,debug:y.debug,asyncMode:y.asyncMode,onRequestFallback:h,onRequestSwitchKernel:c,canvas:y.graphical&&!y.context?y.canvas:null});r.fallbackReason=y.fallbackReason,r.build.apply(r,e);const n=r.run.apply(r,e);return y.replaceKernel(r),!l.canvas&&r.canvas&&(l.canvas=r.canvas),!l.context&&r.context&&(l.context=r.context),n}function c(e,r,n){n.debug&&console.warn("Switching kernels");let s=null;if(n.signature&&!a[n.signature]&&(a[n.signature]=n),n.dynamicOutput)for(let t=e.length-1;t>=0;t--){const r=e[t];"outputPrecisionMismatch"===r.type&&(s=r.needed)}const o=n.constructor,u=o.getArgumentTypes(n,r),l=o.getSignature(n,u),p=a[l];if(p)return p.onActivate(n),p;const d=a[l]=new o(t,{argumentTypes:u,constantTypes:n.constantTypes,graphical:n.graphical,loopMaxIterations:n.loopMaxIterations,constants:n.constants,dynamicOutput:n.dynamicOutput,dynamicArgument:n.dynamicArguments,context:n.context,canvas:n.canvas,output:s||n.output,precision:n.precision,pipeline:n.pipeline,immutable:n.immutable,optimizeFloatMemory:n.optimizeFloatMemory,fixIntegerDivisionAccuracy:n.fixIntegerDivisionAccuracy,functions:n.functions,nativeFunctions:n.nativeFunctions,injectedNative:n.injectedNative,subKernels:n.subKernels,strictIntegers:n.strictIntegers,randomSeed:n.randomSeed,debug:n.debug,asyncMode:n.asyncMode,gpu:n.gpu,validate:v,returnType:n.returnType,tactic:n.tactic,onRequestFallback:h,onRequestSwitchKernel:c,texture:n.texture,mappedTextures:n.mappedTextures,drawBuffersMap:n.drawBuffersMap});return d.build.apply(d,r),y.replaceKernel(d),i.push(d),d}const p=Object.assign({context:this.context,canvas:this.canvas,functions:this.functions,nativeFunctions:this.nativeFunctions,injectedNative:this.injectedNative,gpu:this,validate:v,onRequestFallback:h,onRequestSwitchKernel:c},o);"async"===this.mode&&(p.asyncMode=!0);let f,g=this.Kernel;"async"===this.mode&&o.graphical&&!0===this._webGPUDecision&&(g=d,p.canvas===this.canvas&&(p.canvas=o.canvas||null),p.context===this.context&&(p.context=o.context||null),p.asyncMode=!0);try{f=new g(t,p)}catch(e){if(g===this.Kernel)throw e;f=new this.Kernel(t,Object.assign({},p,{canvas:this.canvas,context:this.context}))}const y=m(f);if("async"===this.mode&&d.isSupported&&!(f instanceof d)){const r=this;f.onAsyncModeUpgrade=function(n,s){return e.isWebGPUAvailable().then(e=>{if(!e)return null;if(s.graphical)return s.debug&&console.warn("webgpu upgrade declined: graphical kernels keep their canvas"),null;let a;try{a=new d(t,{functions:s.functions,nativeFunctions:s.nativeFunctions,injectedNative:s.injectedNative,gpu:r,validate:v,asyncMode:!0,output:s.output,pipeline:s.pipeline,immutable:s.immutable,dynamicOutput:s.dynamicOutput,dynamicArguments:!0,loopMaxIterations:s.loopMaxIterations,constants:s.constants,constantTypes:s.constantTypes,argumentTypes:s.argumentTypes,precision:s.precision,tactic:s.tactic,strictIntegers:s.strictIntegers,fixIntegerDivisionAccuracy:s.fixIntegerDivisionAccuracy,subKernels:s.subKernels,graphical:s.graphical,debug:s.debug}),a.build.apply(a,n)}catch(e){return s.debug&&console.warn("webgpu upgrade declined: "+e.message),null}return a._buildPromise.then(()=>(i.push(a),a),e=>(s.debug&&console.warn("webgpu upgrade declined: "+e.message),a.destroy(),null))},()=>null)}}return this.canvas||(this.canvas=f.canvas),this.context||(this.context=f.context),i.push(f),y}createPipeline(e,t){if("function"!=typeof e)throw new Error("createPipeline requires an orchestration function");if("dev"===this.mode)throw new Error("createPipeline is not supported in dev mode");const r=new g(this,e,t);this.pipelines.push(r);const n=function(){return r.call(arguments)};return n.pipeline=r,n.setConstants=function(e){return r.setConstants(e),n},n.destroy=function(){return r.destroy()},Object.defineProperty(n,"executorKind",{get:()=>r.executorKind}),Object.defineProperty(n,"fallbackReason",{get:()=>r.fallbackReason}),Object.defineProperty(n,"plan",{get:()=>r.plan}),Object.defineProperty(n,"backend",{get:()=>{const e=r.executorKind;if("fused-sync"===e||"fused-threaded"===e)return"webasm";if("fused-encoder"===e)return"webgpu";const t=r.plan;if(!t)return null;for(const[e,r]of t.genericClones)if(0!==e.indexOf("up:"))return r.kernel.constructor.mode;return t.kernels.length>0?t.kernels[0].clone.kernel.constructor.mode:null}}),n}createKernelMap(){let e,t;const r=typeof arguments[arguments.length-2];if("function"===r||"string"===r?(e=arguments[arguments.length-2],t=arguments[arguments.length-1]):e=arguments[arguments.length-1],!("dev"===this.mode||this.Kernel.isSupported&&this.Kernel.features.kernelMap)){if("webgpu"===this.Kernel.mode)throw new Error("WebGPU backend does not yet support createKernelMap");if(this.mode&&x.indexOf(this.mode)<0&&"webasm"!==this.Kernel.mode)throw new Error(`kernelMap not supported on ${this.Kernel.name}`)}const n=T(t);if(t&&"object"==typeof t.argumentTypes&&(n.argumentTypes=Object.keys(t.argumentTypes).map(e=>t.argumentTypes[e])),Array.isArray(arguments[0])){n.subKernels=[];const e=arguments[0];for(let t=0;t0)throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.');return this.nativeFunctions.push(Object.assign({name:e,source:t},r)),this}injectNative(e){return this.injectedNative=e,this}destroy(){return new Promise((e,t)=>{this.kernels||e(),setTimeout(()=>{try{let r=Promise.resolve();if(this.pipelines){const e=this.pipelines.slice();r=Promise.all(e.map(e=>Promise.resolve(e.destroy()).catch(()=>{})))}const n=()=>{try{const e=this.kernels.slice();for(let t=0;t{const{utils:r}=i();t.exports={alias:function(e,t){const n=t.toString();return new Function(`return function ${e} (${r.getArgumentNamesFromString(n).join(", ")}) {\n ${r.getFunctionBodyFromString(n)}\n}`)()}}}),mt=e((e,t)=>{const{GPU:r}=dt(),{alias:c}=ft(),{utils:d}=i(),{Input:f,input:m}=n(),{Texture:g}=s(),{FunctionBuilder:y}=o(),{FunctionNode:x}=l(),{CPUFunctionNode:b}=h(),{CPUKernel:v}=p(),{HeadlessGLKernel:T}=be(),{WebGLFunctionNode:S}=G(),{WebGLKernel:A}=xe(),{kernelValueMaps:w}=ye(),{WebGL2FunctionNode:_}=ve(),{WebGL2Kernel:E}=et(),{kernelValueMaps:I}=Qe(),{WGSLFunctionNode:k}=tt(),{WebGPUKernel:L}=st(),{WebGPUContext:F}=rt(),{WebGPUBufferResult:$}=nt(),{WebAssemblyFunctionNode:C}=at(),{WebAssemblyKernel:M}=ut(),{GLKernel:O}=D(),{Kernel:N}=a(),{FunctionTracer:z}=u();t.exports={alias:c,CPUFunctionNode:b,CPUKernel:v,GPU:r,FunctionBuilder:y,FunctionNode:x,HeadlessGLKernel:T,Input:f,input:m,Texture:g,utils:d,WebGL2FunctionNode:_,WebGL2Kernel:E,webGL2KernelValueMaps:I,WebGLFunctionNode:S,WebGLKernel:A,webGLKernelValueMaps:w,WGSLFunctionNode:k,WebGPUKernel:L,WebGPUContext:F,WebGPUBufferResult:$,WebAssemblyFunctionNode:C,WebAssemblyKernel:M,GLKernel:O,Kernel:N,FunctionTracer:z,plugins:{mathRandom:R()}}});return e((e,t)=>{const r=mt(),n=r.GPU;for(const e in r)r.hasOwnProperty(e)&&"GPU"!==e&&(n[e]=r[e]);function s(e){e.GPU&&e.GPU.prototype&&e.GPU.prototype.createKernel||Object.defineProperty(e,"GPU",{configurable:!0,get:()=>n,set(){}})}n.GPU=n,"undefined"!=typeof window&&s(window),"undefined"!=typeof self&&s(self),t.exports=n})()}); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):(e="undefined"!=typeof globalThis?globalThis:e||self).GPU=t()}(this,function(){var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),t=e((e,t)=>{function n(e){const t=new Array(e.length);for(let n=0;n{e.output=l(t),e.graphical&&u(e)},e.toJSON=()=>{throw new Error("Not usable with gpuMock")},e.setConstants=t=>(e.constants=t,e),e.setGraphical=t=>(e.graphical=t,e),e.setCanvas=t=>(e.canvas=t,e),e.setContext=t=>(e.context=t,e),e.destroy=()=>{},e.validateSettings=()=>{},e.graphical&&e.output&&u(e),e.exec=function(){return new Promise((t,n)=>{try{t(e.apply(e,arguments))}catch(e){n(e)}})},e.getPixels=t=>{const{x:n,y:r}=e.output;return t?function(e,t,n){const r=n/2|0,s=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee,n=["setWarnVarUsage","setArgumentTypes","setTactic","setOptimizeFloatMemory","setDebug","setLoopMaxIterations","setConstantTypes","setFunctions","setNativeFunctions","setInjectedNative","setPipeline","setPrecision","setOutputToTexture","setImmutable","setStrictIntegers","setDynamicOutput","setHardcodeConstants","setDynamicArguments","setUseLegacyEncoder","setWarnVarUsage","addSubKernel"];for(let r=0;r{t.exports={}}),r=e((e,t)=>{var n=class{constructor(e,t){this.value=e,Array.isArray(t)?this.size=t:(this.size=new Int32Array(3),t.z?this.size=new Int32Array([t.x,t.y,t.z]):t.y?this.size=new Int32Array([t.x,t.y]):this.size=new Int32Array([t.x]));const[n,r,s]=this.size;if(s){if(this.value.length!==n*r*s)throw new Error(`Input size ${this.value.length} does not match ${n} * ${r} * ${s} = ${r*n*s}`)}else if(r){if(this.value.length!==n*r)throw new Error(`Input size ${this.value.length} does not match ${n} * ${r} = ${r*n}`)}else if(this.value.length!==n)throw new Error(`Input size ${this.value.length} does not match ${n}`)}toArray(){const{utils:e}=i(),[t,n,r]=this.size;return r?e.erectMemoryOptimized3DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,n,r):n?e.erectMemoryOptimized2DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,n):this.value}};t.exports={Input:n,input:function(e,t){return new n(e,t)}}}),s=e((e,t)=>{t.exports={Texture:class{constructor(e){const{texture:t,size:n,dimensions:r,output:s,context:i,type:a="NumberTexture",kernel:o,internalFormat:u,textureFormat:l}=e;if(!s)throw new Error('settings property "output" required.');if(!i)throw new Error('settings property "context" required.');if(!t)throw new Error('settings property "texture" required.');if(!o)throw new Error('settings property "kernel" required.');this.texture=t,t._refs?t._refs++:t._refs=1,this.size=n,this.dimensions=r,this.output=s,this.context=i,this.kernel=o,this.type=a,this._deleted=!1,this.internalFormat=u,this.textureFormat=l}toArray(){throw new Error(`Not implemented on ${this.constructor.name}`)}clone(){throw new Error(`Not implemented on ${this.constructor.name}`)}delete(){throw new Error(`Not implemented on ${this.constructor.name}`)}clear(){throw new Error(`Not implemented on ${this.constructor.name}`)}}}}),i=e((e,t)=>{const i=n(),{Input:a}=r(),{Texture:o}=s(),u=/function ([^(]*)/,l=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,h=/([^\s,]+)/g,c={systemEndianness:()=>m,getSystemEndianness(){const e=new ArrayBuffer(4),t=new Uint32Array(e),n=new Uint8Array(e);if(t[0]=3735928559,239===n[0])return"LE";if(222===n[0])return"BE";throw new Error("unknown endianness")},isFunction:e=>"function"==typeof e,isFunctionString:e=>"string"==typeof e&&"function"===e.slice(0,8).toLowerCase(),getFunctionNameFromString(e){const t=u.exec(e);return t&&0!==t.length?t[1].trim():null},getFunctionBodyFromString:e=>e.substring(e.indexOf("{")+1,e.lastIndexOf("}")),getArgumentNamesFromString(e){const t=e.replace(l,"");let n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(h);return null===n&&(n=[]),n},clone(e){if(null===e||"object"!=typeof e||e.hasOwnProperty("isActiveClone"))return e;const t=e.constructor();for(let n in e)Object.prototype.hasOwnProperty.call(e,n)&&(e.isActiveClone=null,t[n]=c.clone(e[n]),delete e.isActiveClone);return t},isArray:e=>!isNaN(e.length),typeFitsValue(e,t){if("string"!=typeof e||null==t)return!0;if(t.type)return!0;switch(e){case"Input":return t instanceof a;case"Boolean":return"boolean"==typeof t;case"Number":case"Integer":case"Float":return"number"==typeof t}return-1!==e.indexOf("Texture")?Boolean(t.type):0!==e.indexOf("Array")||c.isArray(t)},getVariableType(e,t){if(c.isArray(e))return e.length>0&&"IMG"===e[0].nodeName?"HTMLImageArray":"Array";switch(e.constructor){case Boolean:return"Boolean";case Number:return t&&Number.isInteger(e)?"Integer":"Float";case o:return e.type;case a:return"Input"}if("nodeName"in e)switch(e.nodeName){case"IMG":case"CANVAS":return"HTMLImage";case"VIDEO":return"HTMLVideo"}else{if(e.hasOwnProperty("type"))return e.type;if("undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return"OffscreenCanvas";if("undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap)return"ImageBitmap";if("undefined"!=typeof ImageData&&e instanceof ImageData)return"ImageData"}return"Unknown"},getKernelTextureSize(e,t){let[n,r,s]=t,i=(n||1)*(r||1)*(s||1);return e.optimizeFloatMemory&&"single"===e.precision&&(n=i=Math.ceil(i/4)),r>1&&n*r===i?new Int32Array([n,r]):c.closestSquareDimensions(i)},closestSquareDimensions(e){const t=Math.sqrt(e);let n=Math.ceil(t),r=Math.floor(t);for(;n*rMath.floor((e+t-1)/t)*t,getDimensions(e,t){let n;if(c.isArray(e)){const t=[];let r=e;for(;c.isArray(r);)t.push(r.length),r=r[0];n=t.reverse()}else if(e instanceof o)n=e.output;else{if(!(e instanceof a))throw new Error(`Unknown dimensions of ${e}`);n=e.size}if(t)for(n=Array.from(n);n.length<3;)n.push(1);return new Int32Array(n)},flatten2dArrayTo(e,t){let n=0;for(let r=0;re.length>0?e.join(";\n")+";\n":"\n",warnDeprecated(e,t,n){n?console.warn(`You are using a deprecated ${e} "${t}". It has been replaced with "${n}". Fixing, but please upgrade as it will soon be removed.`):console.warn(`You are using a deprecated ${e} "${t}". It has been removed. Fixing, but please upgrade as it will soon be removed.`)},flipPixels:(e,t,n)=>{const r=n/2|0,s=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee.subarray(0,t),erect2DPackedFloat:(e,t,n)=>{const r=new Array(n);for(let s=0;s{const s=new Array(r);for(let i=0;ie.subarray(0,t),erectMemoryOptimized2DFloat:(e,t,n)=>{const r=new Array(n);for(let s=0;s{const s=new Array(r);for(let i=0;i{const n=new Float32Array(t);let r=0;for(let s=0;s{const r=new Array(n);let s=0;for(let i=0;i{const s=new Array(r);let i=0;for(let a=0;a{const n=new Array(t),r=4*t;let s=0;for(let t=0;t{const r=new Array(n),s=4*t;for(let i=0;i{const s=4*t,i=new Array(r);for(let a=0;a{const n=new Array(t),r=4*t;let s=0;for(let t=0;t{const r=4*t,s=new Array(n);for(let i=0;i{const s=4*t,i=new Array(r);for(let a=0;a{const n=new Array(e),r=4*t;let s=0;for(let t=0;t{const r=4*t,s=new Array(n);for(let i=0;i{const s=4*t,i=new Array(r);for(let a=0;a{const{findDependency:n,thisLookup:r,doNotDefine:s}=t;let a=t.flattened;a||(a=t.flattened={});const o=i.parse(e,{ecmaVersion:2020}),u=[];let l=0;const h=function e(t){if(Array.isArray(t)){const n=[];for(let r=0;rnull!==e);return s.length<1?"":`${t.kind} ${s.join(",")}`;case"VariableDeclarator":return t.init?t.init.object&&"ThisExpression"===t.init.object.type?r(t.init.property.name,!0)?`${t.id.name} = ${e(t.init)}`:null:`${t.id.name} = ${e(t.init)}`:t.id.name;case"CallExpression":if("subarray"===t.callee.property.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("gl"===t.callee.object.name||"context"===t.callee.object.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("ThisExpression"===t.callee.object.type)return u.push(n("this",t.callee.property.name)),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;if(t.callee.object.name){const r=n(t.callee.object.name,t.callee.property.name);return null===r?`${t.callee.object.name}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`:(u.push(r),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`)}if("MemberExpression"===t.callee.object.type)return`${e(t.callee.object)}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;throw new Error("unknown ast.callee");case"ReturnStatement":return`return ${e(t.argument)}`;case"BinaryExpression":return`(${e(t.left)}${t.operator}${e(t.right)})`;case"UnaryExpression":return t.prefix?`${t.operator} ${e(t.argument)}`:`${e(t.argument)} ${t.operator}`;case"ExpressionStatement":return`${e(t.expression)}`;case"SequenceExpression":return`(${e(t.expressions)})`;case"ArrowFunctionExpression":return`(${t.params.map(e).join(", ")}) => ${e(t.body)}`;case"Literal":return t.raw;case"Identifier":return t.name;case"MemberExpression":return"ThisExpression"===t.object.type?r(t.property.name):t.computed?`${e(t.object)}[${e(t.property)}]`:e(t.object)+"."+e(t.property);case"ThisExpression":return"this";case"NewExpression":return`new ${e(t.callee)}(${t.arguments.map(t=>e(t)).join(", ")})`;case"ForStatement":return`for (${e(t.init)};${e(t.test)};${e(t.update)}) ${e(t.body)}`;case"AssignmentExpression":return`${e(t.left)}${t.operator}${e(t.right)}`;case"UpdateExpression":return`${e(t.argument)}${t.operator}`;case"IfStatement":{const n=e(t.consequent);if(!t.alternate)return`if (${e(t.test)}) ${n}`;const r="BlockStatement"===t.consequent.type?"":";";return`if (${e(t.test)}) ${n}${r} else ${e(t.alternate)}`}case"ThrowStatement":return`throw ${e(t.argument)}`;case"ObjectPattern":return t.properties.map(e).join(", ");case"ArrayPattern":return t.elements.map(e).join(", ");case"DebuggerStatement":return"debugger;";case"ConditionalExpression":return`${e(t.test)}?${e(t.consequent)}:${e(t.alternate)}`;case"Property":if("init"===t.kind)return e(t.key)}throw new Error(`unhandled ast.type of ${t.type}`)}(o);if(u.length>0){const e=[];for(let n=0;n{if("VariableDeclaration"!==e.type)throw new Error('Ast is not of type "VariableDeclaration"');const t=[];for(let n=0;n{const n=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].r},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),r=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].g},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),s=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].b},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),i=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].a},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),a=[n(t),r(t),s(t),i(t)];return a.rKernel=n,a.gKernel=r,a.bKernel=s,a.aKernel=i,a.gpu=e,a},splitRGBAToCanvases:(e,t,n,r)=>{const s=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(t.r/255,0,0,255)},{output:[n,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});s(t);const i=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,t.g/255,0,255)},{output:[n,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});i(t);const a=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,0,t.b/255,255)},{output:[n,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});a(t);const o=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(255,255,255,t.a/255)},{output:[n,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});return o(t),[s.canvas,i.canvas,a.canvas,o.canvas]},getMinifySafeName:e=>{try{const{init:t}=i.parse(`const value = ${e.toString()}`,{ecmaVersion:2020}).body[0].declarations[0];return t.body.name||t.body.body[0].argument.name}catch(e){throw new Error("Unrecognized function type. Please use `() => yourFunctionVariableHere` or function() { return yourFunctionVariableHere; }")}},sanitizeName:function(e){return p.test(e)&&(e=e.replace(p,"S_S")),d.test(e)?e=e.replace(d,"U_U"):f.test(e)&&(e=e.replace(f,"u_u")),e}},p=/\$/,d=/__/,f=/_/,m=c.getSystemEndianness();t.exports={utils:c}}),a=e((e,t)=>{const{utils:n}=i(),{Input:s}=r();t.exports={Kernel:class{static get isSupported(){throw new Error(`"isSupported" not implemented on ${this.name}`)}static isContextMatch(e){throw new Error(`"isContextMatch" not implemented on ${this.name}`)}static getFeatures(){throw new Error(`"getFeatures" not implemented on ${this.name}`)}static destroyContext(e){throw new Error(`"destroyContext" called on ${this.name}`)}static nativeFunctionArguments(){throw new Error(`"nativeFunctionArguments" called on ${this.name}`)}static nativeFunctionReturnType(){throw new Error(`"nativeFunctionReturnType" called on ${this.name}`)}static combineKernels(){throw new Error(`"combineKernels" called on ${this.name}`)}constructor(e,t){if("object"!=typeof e){if("string"!=typeof e)throw new Error("source not a string");if(!n.isFunctionString(e))throw new Error("source not a function string")}this.useLegacyEncoder=!1,this.fallbackRequested=!1,this.fallbackReason=null,this.onRequestFallback=null,this.onRequestSwitchKernel=null,this.argumentNames="string"==typeof e?n.getArgumentNamesFromString(e):null,this.argumentTypes=null,this.declaredArgumentTypes=null,this.argumentSizes=null,this.argumentBitRatios=null,this.kernelArguments=null,this.kernelConstants=null,this.forceUploadKernelConstants=null,this.source=e,this.output=null,this.debug=!1,this.graphical=!1,this.loopMaxIterations=0,this.constants=null,this.constantTypes=null,this.constantBitRatios=null,this.dynamicArguments=!1,this.dynamicOutput=!1,this.canvas=null,this.context=null,this.checkContext=null,this.gpu=null,this.functions=null,this.nativeFunctions=null,this.injectedNative=null,this.subKernels=null,this.validate=!0,this.immutable=!1,this.pipeline=!1,this.asyncMode=!1,this.precision=null,this.tactic=null,this.plugins=null,this.returnType=null,this.leadingReturnStatement=null,this.followingReturnStatement=null,this.optimizeFloatMemory=null,this.strictIntegers=!1,this.fixIntegerDivisionAccuracy=null,this._optimizerDisabled=!1,this._inliningDisabled=!1,this.localizeThreadCoordinates=!1,this.loopUnrollLimit=8,this.randomSeed=null,this.built=!1,this.signature=null,this.switchingKernels=null}mergeSettings(e){for(let t in e)if(e.hasOwnProperty(t)&&this.hasOwnProperty(t)){switch(t){case"argumentTypes":this.argumentTypes=e[t],e[t]&&(this.declaredArgumentTypes=Array.isArray(e[t])?e[t].slice():e[t]);continue;case"output":if(!Array.isArray(e.output)){this.setOutput(e.output);continue}break;case"functions":this.functions=[];for(let t=0;te.name):null,returnType:this.returnType}}}buildSignature(e){const t=this.constructor;this.signature=t.getSignature(this,t.getArgumentTypes(this,e))}static getArgumentTypes(e,t){const r=new Array(t.length);for(let s=0;st.argumentTypes[e])||[];const i=Object.keys(t.argumentTypes);if(i.length>0&&e.length>0&&s.every(e=>void 0===e))throw new Error(`argumentTypes keys [${i.join(", ")}] match none of the function's parameters [${e.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${i.map(e=>t.argumentTypes[e]).join("', '")}']`)}else s=t.argumentTypes||[];return{name:t.name||n.getFunctionNameFromString(r)||("function"==typeof e&&e.name?e.name:null),source:r,argumentTypes:s,returnType:t.returnType||null}}onActivate(e){}switchKernels(e){this.switchingKernels?this.switchingKernels.push(e):this.switchingKernels=[e]}resetSwitchingKernels(){const e=this.switchingKernels;return this.switchingKernels=null,e}checkArgumentTypes(e){if(!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let r=0;r{let n=1610612736;function r(e,t){return e.start=n++,e.end=n++,t&&t.loc&&(e.loc=t.loc),e}const s=["Number","Float","Integer"],i="@this",a=["value[]","value[][]","value[][][]","value[][][][]","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]"];var o=class{constructor(e,t,n){this.functionNode=e,this.ast=t,this.loopUnrollLimit="number"==typeof n.loopUnrollLimit?n.loopUnrollLimit:8,this.lookupInlineTarget=n.lookupInlineTarget||null,this.inlineTargets=new Map,this.inlineCount=0,this.mutatedNames=h(t.body),this.usedNames=function(e){const t=new Set;return u(e,e=>{"Identifier"===e.type&&t.add(e.name)}),t}(t),this.hoistCount=0}freshName(){let e;do{e="optHoist"+this.hoistCount++}while(this.usedNames.has(e));return this.usedNames.add(e),e}freshInlineName(e){let t;do{t=`optIn${this.inlineCount++}_${e}`}while(this.usedNames.has(t));return this.usedNames.add(t),t}inlineTarget(e){if(!this.lookupInlineTarget)return null;if(this.inlineTargets.has(e))return this.inlineTargets.get(e);let t=null;try{t=this.lookupInlineTarget(e)||null}catch(e){t=null}return this.inlineTargets.set(e,t),t}isImmutableArrayRoot(e){if(this.mutatedNames.has(e))return!1;const{argumentNames:t}=this.functionNode;return Boolean(t)&&t.indexOf(e)>-1}readElementType(e,t){const n=this.readRootType(e,t);if(!n)return null;try{return this.functionNode.getLookupType(n)}catch(e){return null}}readRootType(e,t){const{functionNode:n}=this;if(0===t.indexOf("this.constants.")){if(this.mutatedNames.has(i))return null;const r=function(e,t){let n=(t.match(/\[\]/g)||[]).length,r=e;for(;n-- >0;){if(!r||"MemberExpression"!==r.type)return null;r=r.object}return r&&r.property&&r.property.name?r.property.name:null}(e,t);if(!r)return null;const s=n.constantTypes?n.constantTypes[r]:null;return"Float"===s?"Number":s||null}const r=c(e);if(!r||"Identifier"!==r.type)return null;if(!this.isImmutableArrayRoot(r.name))return null;const s=n.argumentNames.indexOf(r.name);return(n.argumentTypes?n.argumentTypes[s]:null)||null}};function u(e,t){if(e&&"object"==typeof e)if(Array.isArray(e))for(let n=0;n{let n=e;for(;n&&"MemberExpression"===n.type;)n=n.object;n&&"Identifier"===n.type&&t.add(n.name),n&&"ThisExpression"===n.type&&t.add(i)};return u(e,e=>{switch(e.type){case"AssignmentExpression":n(e.left);break;case"UpdateExpression":n(e.argument);break;case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.add(e.id.name);break;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":e.id&&e.id.name&&t.add(e.id.name);for(let n=0;n0&&(n.splice(t,0,...r),t+=r.length)}}function d(e,t){switch(t.type){case"BlockStatement":return p(e,t),null;case"IfStatement":return f(e,t,"consequent"),f(e,t,"alternate"),null;case"SwitchStatement":for(let n=0;n":return r>n;case">=":return r>=n;case"!==":case"!=":return r!==n;default:return!1}}(t),i=[],a=new Set,o=new Map;for(let t=0;t0)for(let e=0;ea.has(e)))continue;const n=t.filter(e=>!a.has(e));t.length=0;for(let e=0;e0&&(t[n]=r({type:"BlockStatement",body:i.concat([s])},s))}function m(e,t){for(let n=0;n{if(e&&"object"==typeof e&&!t)if(Array.isArray(e))for(let t=0;t{const c=t[h];if(c&&"object"==typeof c)if(Array.isArray(c))for(let e=0;e{if(n||"MemberExpression"!==t.type)return;const r=e.functionNode.getVariableSignature(t);r&&-1!==a.indexOf(r)&&(!e.functionNode.readsFaultAtOneLevel&&(r.match(/\[\]/g)||[]).length<2||"Input"!==e.readRootType(t,r)&&(n=!0))}),n}function b(e){if(!e)return null;if("Literal"===e.type&&"number"==typeof e.value)return e.value;if("UnaryExpression"===e.type&&"-"===e.operator){const t=b(e.argument);return null===t?null:-t}return null}function v(e,t,n){if(!t||"object"!=typeof t)return!1;switch(t.type){case"Literal":case"ThisExpression":return!0;case"Identifier":return!n.has(t.name);case"UnaryExpression":return"delete"!==t.operator&&"typeof"!==t.operator&&v(e,t.argument,n);case"BinaryExpression":case"LogicalExpression":return v(e,t.left,n)&&v(e,t.right,n);case"ConditionalExpression":return v(e,t.test,n)&&v(e,t.consequent,n)&&v(e,t.alternate,n);case"MemberExpression":return function(e,t,n){const r=e.functionNode.getVariableSignature(t);if(!r)return!1;switch(r){case"this.thread.value":case"this.output.value":return!0;case"this.constants.value":return!e.mutatedNames.has(i);case"value.value":return e.functionNode.isAstMathVariable(t);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":{const r=c(t);return!(!r||"Identifier"!==r.type||!e.isImmutableArrayRoot(r.name))&&S(e,t,n)}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":return!e.mutatedNames.has(i)&&S(e,t,n);default:return!1}}(e,t,n);default:return!1}}function S(e,t,n){let r=t;for(;r&&"MemberExpression"===r.type;){if(r.computed&&!v(e,r.property,n))return!1;r=r.object}return!0}function T(e){if(!e||"object"!=typeof e)return null;switch(e.type){case"Literal":return`L${typeof e.value}:${e.value}`;case"ThisExpression":return"this";case"Identifier":return`#${e.name}`;case"MemberExpression":{const t=T(e.object),n=T(e.property);return null===t||null===n?null:`M${e.computed?"[":"."}(${t},${n})`}case"UnaryExpression":{const t=T(e.argument);return null===t?null:`U${e.operator}(${t})`}case"BinaryExpression":case"LogicalExpression":{const t=T(e.left),n=T(e.right);return null===t||null===n?null:`B${e.operator}(${t},${n})`}default:return null}}const A=6e3,w=2e4;function E(e,t){e.lookupInlineTarget&&(t.body=I(e,t.body))}function I(e,t){const n=[],s=t.slice();let i=0;for(;s.length>0;){if(++i>w)throw new Error("optimizer: inlining did not converge");const t=s.shift(),a=[],o=L(e,t,a);if(o.expanded>0){const e=o.consumed?r({type:"EmptyStatement"},t):t;s.unshift(...a,e);continue}_(e,t),n.push(t)}return n}function _(e,t){switch(t.type){case"BlockStatement":return void E(e,t);case"IfStatement":return t.consequent=k(e,t.consequent),void(t.alternate&&(t.alternate=k(e,t.alternate)));case"ForStatement":case"WhileStatement":case"DoWhileStatement":return void(t.body=k(e,t.body));case"SwitchStatement":for(let n=0;ne.inlineTarget(t),sites:[],clean:!0},r=F(t);for(let e=0;e{"CallExpression"!==e.type?"AssignmentExpression"!==e.type&&"UpdateExpression"!==e.type||(t.clean=!1):R(e)||(t.clean=!1)})}function M(e){return e.callee&&"Identifier"===e.callee.type?e.callee.name:null}function R(e){const{callee:t}=e;return Boolean(t)&&"MemberExpression"===t.type&&!t.computed&&t.object&&"Identifier"===t.object.type&&"Math"===t.object.name&&t.property&&"random"!==t.property.name}function G(e,t,n){const{node:r,entry:s,parent:i,key:a}=t,o=new Map;for(let t=0;t{u.set(t,e.freshInlineName(t))});const l=B(z(e,s.body,o,u));if(!l)throw new Error("optimizer: helper body no longer reduces");for(let e=0;e=e.length)return null;const n=e[t];if("ReturnStatement"===n.type)return t===e.length-1&&n.argument?n.argument:null;if("IfStatement"!==n.type)return null;const s=P(n.consequent);if(null===s)return null;let i;if(n.alternate){if(t!==e.length-1)return null;i=P(n.alternate)}else i=U(e,t+1);if(null===i)return null;if(!j(s)||!j(i))return null;const a=K(s),o=K(i);return"unknown"!==a&&"unknown"!==o&&a!==o?null:r({type:"ConditionalExpression",test:n.test,consequent:s,alternate:i},n)}function K(e){if(!e)return"unknown";if("Literal"===e.type&&"number"==typeof e.value)return Number.isInteger(e.value)?"int":"float";if("BinaryExpression"===e.type&&"+-*/".indexOf(e.operator)>-1){const t=K(e.left),n=K(e.right);return"float"===t||"float"===n?"float":"unknown"===t||"unknown"===n||"/"===e.operator?"unknown":"int"}return"unknown"}function P(e){return e?U("BlockStatement"===e.type?e.body:[e],0):null}function W(e){let t=!1;return u(e,e=>{"ReturnStatement"===e.type&&(t=!0)}),t}function j(e){let t=!0;return u(e,e=>{"CallExpression"!==e.type||R(e)||(t=!1)}),t}function q(e,t,n,r,s){e.has(t)||e.set(t,{name:t,ast:n,kind:r,params:(n.params||[]).map(e=>"Identifier"===e.type?e.name:null),body:n.body.body,assignedParams:new Set,localNames:new Set,returnsValue:!1,inlinable:"helper"===r,recursive:!1,calls:[],sites:[],selfSize:0,expandedSize:0});const i=[];u(n.body,e=>{"FunctionDeclaration"===e.type&&e.id&&e.id.name&&i.push(e)});for(let t=0;t{t++}),t}(e.body);const n=new Set,r=new Set,s=new Set;let i=!1,a=!1;u(e.body,e=>{"CallExpression"===e.type&&e.callee&&"MemberExpression"===e.callee.type&&e.callee.object&&"Math"===e.callee.object.name&&e.callee.property&&"random"===e.callee.property.name&&(a=!0)});const o=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t-1||t.has(r)))return void(e.inlinable=!1);e.localNames=n;for(let t=0;t320&&(e.inlinable=!1)):e.inlinable=!1}function H(e,t,n){const r=new Set,s={candidates:t=>{const n=e.get(t);return n&&n.inlinable&&!n.recursive?n:null},sites:[],clean:!0},i=e=>{for(let t=0;t{if(!e||"string"!=typeof e.type)return;if("FunctionDeclaration"===e.type)return;s.clean=!0,s.sites=[];const n=F(e);for(let e=0;e{if("CallExpression"!==t.type||r.has(t))return;const s=M(t);s&&e.has(s)&&n.add(s)});for(let e=0;e320&&(t.inlinable=!1,n=!0);t=!0;let r=null,s=6e3;for(const t of e.values()){let n=0;for(let r=0;rs&&(s=n,r=t)}if(!r)break;let i=null;for(let t=0;ti.expandedSize||n.expandedSize===i.expandedSize&&n.name0))return null;if("ForStatement"!==t.type)return null;const n=function(e,t){const{init:n}=t;if(!n||"VariableDeclaration"!==n.type)return null;if(1!==n.declarations.length)return null;const r=n.declarations[0];if(!r.id||"Identifier"!==r.id.type)return null;const s=re(r.init);return null===s||"var"===n.kind&&function(e,t,n){let r=!1;const s=e=>{if(!r&&e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t=n)return null;u.push(l),l+=o}return u}(t,n,e.loopUnrollLimit);if(!s)return null;if(t.init&&"VariableDeclaration"===t.init.type&&"Literal"!==t.init.declarations[0].init.type){const t=e.functionNode.loopMaxIterations||1e3;if(s.length>t)return null}const i=t.body?"BlockStatement"===t.body.type?t.body.body:[t.body]:[];if(!function(e,t){let n=!0;const r=()=>{n=!1},s=(e,i,a)=>{if(n&&e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t{t++}),t}(i)*(s.length-1);void 0===e.unrollAdded&&(e.unrollAdded=0);if(e.unrollAdded+a>A)return null;e.unrollAdded+=a;const o=[];for(let a=0;aee<=t,">":(e,t)=>e>t,">=":(e,t)=>e>=t,"!==":(e,t)=>e!==t,"!=":(e,t)=>e!==t};function re(e){const t=b(e);return null!==t&&Number.isInteger(t)?t:null}function se(e,t,n,r){const s=new Array(t.length);for(let i=0;i=0?n:r({type:"UnaryExpression",operator:"-",prefix:!0,argument:n},t)}(s,t);const i={},a="MemberExpression"===t.type&&!t.computed;for(const r in t)"start"!==r&&"end"!==r&&(i[r]="loc"!==r&&"range"!==r&&"parent"!==r?ie(e,t[r],a&&"property"===r?null:n,s):t[r]);return r(i,t)}t.exports={optimize:function(e,t,n){if(!t||!t.body||"BlockStatement"!==t.body.type)return t;const r=new o(e,t,n||{});return p(r,t.body),E(r,t.body),J(r,t.body),t},buildInlinePlan:function(e){const t=new Map,n=e.kernel||{},r=new Set(["Math","Infinity"]);if(n.constants)for(const e in n.constants)r.add(e);for(let t=0;t-1,o=Boolean(s.hasDeclaredTypes);q(t,n,i,s.isRootKernel?"root":s.isSubKernel||a||o?"subKernel":"helper",r)}for(const e of t.values())r.add(e.name);for(const e of t.values())X(e,r);let s=!0;for(;s;){s=!1;for(const e of t.values())if(!e.hasEffects)for(let n=0;n{if("CallExpression"!==t.type)return;const n=M(t);n&&e.has(n)&&r.add(n)}),t.set(n.name,r)}const n=new Map,r=[],s=i=>{if("done"!==n.get(i))if("open"!==n.get(i)){n.set(i,"open"),r.push(i);for(const e of t.get(i)||[])s(e);r.pop(),n.set(i,"done")}else for(let t=r.lastIndexOf(i);t1&&(e.inlinable=!1,e.sites=[]);return a},threadLocalName:function(e,t){if(!e.localizeThreadCoordinates)return null;if(e.optimizerDisabled||!e.isRootKernel)return null;const{output:n}=e;if(!n||!n.length)return null;switch(t){case"x":return"x";case"y":return n.length>1?"y":"0";case"z":return n.length>2?"z":"0";default:return null}}}}),u=e((e,t)=>{const{buildInlinePlan:n}=o();t.exports={FunctionBuilder:class e{static fromKernel(t,n,r){const{kernelArguments:s,kernelConstants:i,argumentNames:a,argumentSizes:o,argumentBitRatios:u,constants:l,constantBitRatios:h,debug:c,loopMaxIterations:p,nativeFunctions:d,output:f,optimizeFloatMemory:m,precision:g,plugins:y,source:x,subKernels:b,functions:v,leadingReturnStatement:S,followingReturnStatement:T,dynamicArguments:A,dynamicOutput:w,loopUnrollLimit:E,localizeThreadCoordinates:I}=t,_=Boolean(t._optimizerDisabled),k=Boolean(t._inliningDisabled),L=new Array(s.length),F={};for(let e=0;eq.needsArgumentType(e,t),$=(e,t,n)=>{q.assignArgumentType(e,t,n)},C=(e,t,n)=>q.lookupReturnType(e,t,n),M=e=>q.lookupFunctionArgumentTypes(e),R=(e,t)=>q.lookupFunctionArgumentName(e,t),G=(e,t)=>q.lookupFunctionArgumentBitRatio(e,t),N=(e,t,n,r)=>{q.assignArgumentType(e,t,n,r)},O=(e,t,n,r)=>{q.assignArgumentBitRatio(e,t,n,r)},z=(e,t,n)=>{q.trackFunctionCall(e,t,n)},V=k?null:e=>q.lookupInlineTarget(e),B=(e,t)=>{const r=[];for(let t=0;tnew n(e.source,{name:e.name||void 0,returnType:e.returnType,argumentTypes:e.argumentTypes,hasDeclaredTypes:Boolean(e.returnType)||(Array.isArray(e.argumentTypes)?e.argumentTypes.some(e=>Boolean(e)):Boolean(e.argumentTypes&&Object.keys(e.argumentTypes).length>0)),output:f,plugins:y,constants:l,constantTypes:F,constantBitRatios:h,optimizeFloatMemory:m,precision:g,lookupReturnType:C,lookupFunctionArgumentTypes:M,lookupFunctionArgumentName:R,lookupFunctionArgumentBitRatio:G,needsArgumentType:D,assignArgumentType:$,triggerImplyArgumentType:N,triggerImplyArgumentBitRatio:O,onFunctionCall:z,onNestedFunction:B,optimizerDisabled:_,loopUnrollLimit:E,localizeThreadCoordinates:I,lookupInlineTarget:V})));let j=null;b&&(j=b.map(e=>{const{name:t,source:r}=e;return new n(r,Object.assign({},U,{name:t,isSubKernel:!0,isRootKernel:!1}))}));const q=new e({kernel:t,rootNode:P,functionNodes:W,nativeFunctions:d,subKernelNodes:j});return q}constructor(e){if(e=e||{},this.kernel=e.kernel,this.rootNode=e.rootNode,this.functionNodes=e.functionNodes||[],this.subKernelNodes=e.subKernelNodes||[],this.nativeFunctions=e.nativeFunctions||[],this.functionMap={},this.nativeFunctionNames=[],this.lookupChain=[],this.functionNodeDependencies={},this.functionCalls={},this._inlinePlan=null,this.rootNode&&(this.functionMap.kernel=this.rootNode),this.functionNodes)for(let e=0;e-1){const n=t.indexOf(e);if(-1===n)t.push(e);else{const e=t.splice(n,1)[0];t.push(e)}return t}const n=this.functionMap[e];if(n){const r=t.indexOf(e);if(-1===r){t.push(e),n.toString();for(let e=0;e-1){t.push(this.nativeFunctions[s].source);continue}const i=this.functionMap[r];i&&t.push(i.toString())}return t}toJSON(){return this.traceFunctionCalls(this.rootNode.name).reverse().map(e=>{const t=this.nativeFunctions.indexOf(e);if(t>-1)return{name:e,source:this.nativeFunctions[t].source};if(this.functionMap[e])return this.functionMap[e].toJSON();throw new Error(`function ${e} not found`)})}fromJSON(e,t){this.functionMap={};for(let n=0;n0){const s=t.arguments;for(let t=0;t{const{utils:n}=i();function r(e){return e.length>0?e[e.length-1]:null}const s="trackIdentifiers",a="memberExpression",o="inForLoopInit";t.exports={FunctionTracer:class{constructor(e){this.runningContexts=[],this.functionContexts=[],this.contexts=[],this.functionCalls=[],this.declarations=[],this.identifiers=[],this.functions=[],this.returnStatements=[],this.trackedIdentifiers=null,this.states=[],this.newFunctionContext(),this.scan(e)}isState(e){return this.states[this.states.length-1]===e}hasState(e){return this.states.indexOf(e)>-1}pushState(e){this.states.push(e)}popState(e){if(!this.isState(e))throw new Error(`Cannot pop the non-active state "${e}"`);this.states.pop()}get currentFunctionContext(){return r(this.functionContexts)}get currentContext(){return r(this.runningContexts)}newFunctionContext(){const e={"@contextType":"function"};this.contexts.push(e),this.functionContexts.push(e)}newContext(e){const t=Object.assign({"@contextType":"const/let"},this.currentContext);this.contexts.push(t),this.runningContexts.push(t),e();const{currentFunctionContext:n}=this;for(const e in n)n.hasOwnProperty(e)&&!t.hasOwnProperty(e)&&(t[e]=n[e]);return this.runningContexts.pop(),t}useFunctionContext(e){const t=r(this.functionContexts);this.runningContexts.push(t),e(),this.runningContexts.pop()}getIdentifiers(e){const t=this.trackedIdentifiers=[];return this.pushState(s),e(),this.trackedIdentifiers=null,this.popState(s),t}getDeclaration(e){const{currentContext:t,currentFunctionContext:n,runningContexts:r}=this,s=t[e]||n[e]||null;if(!s&&t===n&&r.length>0){const t=r[r.length-2];if(t[e])return t[e]}return s}scan(e){if(e)if(Array.isArray(e))for(let t=0;t{this.scan(e.body)});break;case"BlockStatement":this.newContext(()=>{this.scan(e.body)});break;case"AssignmentExpression":case"LogicalExpression":case"BinaryExpression":this.scan(e.left),this.scan(e.right);break;case"UpdateExpression":if("++"===e.operator){const t=this.getDeclaration(e.argument.name);t&&(t.suggestedType="Integer")}this.scan(e.argument);break;case"UnaryExpression":this.scan(e.argument);break;case"VariableDeclaration":"var"===e.kind?this.useFunctionContext(()=>{e.declarations=n.normalizeDeclarations(e),this.scan(e.declarations)}):(e.declarations=n.normalizeDeclarations(e),this.scan(e.declarations));break;case"VariableDeclarator":{const{currentContext:t}=this,n=this.hasState(o),r={ast:e,context:t,name:e.id.name,origin:"declaration",inForLoopInit:n,inForLoopTest:null,assignable:t===this.currentFunctionContext||!n&&!t.hasOwnProperty(e.id.name),suggestedType:null,valueType:null,dependencies:null,isSafe:null};t[e.id.name]||(t[e.id.name]=r),this.declarations.push(r),this.scan(e.id),this.scan(e.init);break}case"FunctionExpression":case"FunctionDeclaration":0===this.runningContexts.length?this.scan(e.body):this.functions.push(e);break;case"IfStatement":this.scan(e.test),this.scan(e.consequent),e.alternate&&this.scan(e.alternate);break;case"ForStatement":{let t;const n=this.newContext(()=>{this.pushState(o),this.scan(e.init),this.popState(o),t=this.getIdentifiers(()=>{this.scan(e.test)}),this.scan(e.update),this.newContext(()=>{this.scan(e.body)})});if(t)for(const e in n)"@contextType"!==e&&t.indexOf(e)>-1&&(n[e].inForLoopTest=!0);break}case"DoWhileStatement":case"WhileStatement":this.newContext(()=>{this.scan(e.body),this.scan(e.test)});break;case"Identifier":this.isState(s)&&this.trackedIdentifiers.push(e.name),this.identifiers.push({context:this.currentContext,declaration:this.getDeclaration(e.name),ast:e});break;case"ReturnStatement":this.returnStatements.push(e),this.scan(e.argument);break;case"MemberExpression":this.pushState(a),this.scan(e.object),this.scan(e.property),this.popState(a);break;case"ExpressionStatement":this.scan(e.expression);break;case"SequenceExpression":this.scan(e.expressions);break;case"CallExpression":this.functionCalls.push({context:this.currentContext,ast:e}),this.scan(e.arguments);break;case"ArrayExpression":this.scan(e.elements);break;case"ConditionalExpression":this.scan(e.test),this.scan(e.alternate),this.scan(e.consequent);break;case"SwitchStatement":this.scan(e.discriminant),this.scan(e.cases);break;case"SwitchCase":this.scan(e.test),this.scan(e.consequent);break;case"ThisExpression":case"Literal":case"DebuggerStatement":case"EmptyStatement":case"BreakStatement":case"ContinueStatement":break;default:throw new Error(`unhandled type "${e.type}"`)}}}}}),h=e((e,t)=>{const r=n(),{utils:s}=i(),{FunctionTracer:a}=l(),{optimize:u}=o(),h=["E","PI","SQRT2","SQRT1_2","LN2","LN10","LOG2E","LOG10E"],c=["abs","acos","acosh","asin","asinh","atan","atan2","atanh","cbrt","ceil","clz32","cos","cosh","expm1","exp","floor","fround","imul","log","log2","log10","log1p","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc"],p=["value","value[]","value[][]","value[][][]","value[][][][]","value.value","value.thread.value","this.thread.value","this.output.value","this.constants.value","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]","fn()[]","fn()[][]","fn()[][][]","[][]"];const d={Number:"Number",Float:"Float",Integer:"Integer",Array:"Number","Array(2)":"Number","Array(3)":"Number","Array(4)":"Number","Matrix(2)":"Number","Matrix(3)":"Number","Matrix(4)":"Number",Array2D:"Number",Array3D:"Number",Input:"Number",HTMLCanvas:"Array(4)",OffscreenCanvas:"Array(4)",HTMLImage:"Array(4)",ImageBitmap:"Array(4)",ImageData:"Array(4)",HTMLVideo:"Array(4)",HTMLImageArray:"Array(4)",NumberTexture:"Number",MemoryOptimizedNumberTexture:"Number","Array1D(2)":"Array(2)","Array1D(3)":"Array(3)","Array1D(4)":"Array(4)","Array2D(2)":"Array(2)","Array2D(3)":"Array(3)","Array2D(4)":"Array(4)","Array3D(2)":"Array(2)","Array3D(3)":"Array(3)","Array3D(4)":"Array(4)","ArrayTexture(1)":"Number","ArrayTexture(2)":"Array(2)","ArrayTexture(3)":"Array(3)","ArrayTexture(4)":"Array(4)"};let f=536870912;function m(e,t){return e.start=f++,e.end=f++,t&&t.loc&&(e.loc=t.loc),e}function g(e,t){return e&&e.body&&"BlockStatement"===e.body.type?(y(e.body,t),e):e}function y(e,t){e.body=x(e.body,t)}function x(e,t){const n=[];for(let r=0;r{if(!e||"object"!=typeof e||n)return e;if(Array.isArray(e))return e.map(r);switch(e.type){case"ContinueStatement":return e.label?(n=!0,e):m({type:"BlockStatement",body:[...w(t),e]},e);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionExpression":case"FunctionDeclaration":case"ArrowFunctionExpression":default:return e;case"IfStatement":return e.consequent=r(e.consequent),e.alternate&&(e.alternate=r(e.alternate)),e;case"BlockStatement":return e.body=e.body.map(r),e;case"SwitchStatement":for(let t=0;t0?(n.push(e),n):[e]}case"WhileStatement":case"DoWhileStatement":return e.body&&(e.body=v(e.body,t)),[e];case"SwitchStatement":for(let n=0;n0&&this.argumentTypes.length!==this.argumentNames.length)throw new Error(`argumentTypes count of ${this.argumentTypes.length} exceeds ${this.argumentNames.length}`);if(this.output.length<1)throw new Error("this.output is not big enough")}isIdentifierConstant(e){return!!this.constants&&this.constants.hasOwnProperty(e)}isInput(e){return"Input"===this.argumentTypes[this.argumentNames.indexOf(e)]}pushState(e){this.states.push(e)}popState(e){if(this.state!==e)throw new Error(`Cannot popState ${e} when in ${this.state}`);this.states.pop()}isState(e){return this.state===e}get state(){return this.states[this.states.length-1]}astMemberExpressionUnroll(e){if("Identifier"===e.type)return e.name;if("ThisExpression"===e.type)return"this";if("MemberExpression"===e.type&&e.object&&e.property)return e.object.hasOwnProperty("name")&&"Math"!==e.object.name?this.astMemberExpressionUnroll(e.property):this.astMemberExpressionUnroll(e.object)+"."+this.astMemberExpressionUnroll(e.property);if(e.hasOwnProperty("expressions")){const t=e.expressions[0];if("Literal"===t.type&&0===t.value&&2===e.expressions.length)return this.astMemberExpressionUnroll(e.expressions[1])}throw this.astErrorOutput("Unknown astMemberExpressionUnroll",e)}get requiresSequenceFreeForInit(){return!1}get readsCanFault(){return!1}get readsFaultAtOneLevel(){return!1}getRawAST(e){if(this._rawAST)return this._rawAST;if("object"==typeof this.source)return g(this.source,this.requiresSequenceFreeForInit),this._rawAST=this.source;if(null===(e=e||r))throw new Error("Missing JS to AST parser");const t=Object.freeze(e.parse(`const parser_${this.name} = ${this.source};`,{locations:!0,ecmaVersion:2020})).body[0].declarations[0].init;return g(t,this.requiresSequenceFreeForInit),this._rawAST=t}getJsAST(e){if(this.ast)return this.ast;const t=this.getRawAST(e);try{this.optimizeAST(t)}catch(e){throw e&&"object"==typeof e&&(e.isOptimizerFailure=!0),e}return this.traceFunctionAST(t),this.ast=t}optimizeAST(e){return this.optimizerDisabled?e:u(this,e,{loopUnrollLimit:this.loopUnrollLimit,lookupInlineTarget:this.lookupInlineTarget})}getAssignedArguments(){if(this._assignedArguments)return this._assignedArguments;const e=new Set,t=new Set,n=this.argumentNames||[],r=s=>{if(s&&"object"==typeof s)if(Array.isArray(s))for(const e of s)r(e);else{"AssignmentExpression"===s.type&&"Identifier"===s.left.type&&-1!==n.indexOf(s.left.name)&&e.add(s.left.name),"UpdateExpression"===s.type&&"Identifier"===s.argument.type&&-1!==n.indexOf(s.argument.name)&&e.add(s.argument.name),"VariableDeclarator"===s.type&&"Identifier"===s.id.type&&-1!==n.indexOf(s.id.name)&&t.add(s.id.name);for(const e in s){if("loc"===e||"range"===e||"parent"===e)continue;const t=s[e];t&&"object"==typeof t&&r(t)}}};r(this.getJsAST());for(const n of t)e.delete(n);return this._assignedArguments=e}traceFunctionAST(e){const{contexts:t,declarations:n,functions:r,identifiers:s,functionCalls:i}=new a(e);this.contexts=t,this.identifiers=s,this.functionCalls=i,this.functions=r;for(let e=0;e":case"<":return"Boolean";case"&":case"|":case"^":case"<<":case">>":case">>>":return"Integer"}const n=this.getType(e.left);if(this.isState("skip-literal-correction"))return n;if("LiteralInteger"===n){const t=this.getType(e.right);return"LiteralInteger"===t?e.left.value%1==0?"Integer":"Float":t}if("Integer"===n){const t=this.getType(e.right);if("Number"===t||"Float"===t)return t}return d[n]||n;case"UpdateExpression":case"ReturnStatement":return this.getType(e.argument);case"UnaryExpression":return"~"===e.operator?"Integer":this.getType(e.argument);case"VariableDeclaration":{const t=e.declarations;let n;for(let e=0;ee.isSafe)}getDependencies(e,t,n){if(t||(t=[]),!e)return null;if(Array.isArray(e)){for(let r=0;r-1/0&&e.value<1/0&&!isNaN(e.value))});break;case"VariableDeclarator":return this.getDependencies(e.init,t,n);case"Identifier":const r=this.getDeclaration(e);if(r)t.push({name:e.name,origin:"declaration",isSafe:!n&&this.isSafeDependencies(r.dependencies)});else if(this.argumentNames.indexOf(e.name)>-1)t.push({name:e.name,origin:"argument",isSafe:!1});else if(this.strictTypingChecking)throw new Error(`Cannot find identifier origin "${e.name}"`);break;case"FunctionDeclaration":return this.getDependencies(e.body.body[e.body.body.length-1],t,n);case"ReturnStatement":return this.getDependencies(e.argument,t);case"BinaryExpression":case"LogicalExpression":return n="/"===e.operator||"*"===e.operator,this.getDependencies(e.left,t,n),this.getDependencies(e.right,t,n),t;case"UnaryExpression":case"UpdateExpression":return this.getDependencies(e.argument,t,n);case"VariableDeclaration":return this.getDependencies(e.declarations,t,n);case"ArrayExpression":return t.push({origin:"declaration",isSafe:!0}),t;case"CallExpression":return t.push({origin:"function",isSafe:!0}),t;case"MemberExpression":const s=this.getMemberExpressionDetails(e);switch(s.signature){case"value[]":this.getDependencies(e.object,t,n);break;case"value[][]":this.getDependencies(e.object.object,t,n);break;case"value[][][]":this.getDependencies(e.object.object.object,t,n);break;case"this.output.value":this.dynamicOutput&&t.push({name:s.name,origin:"output",isSafe:!1})}if(s)return s.property&&this.getDependencies(s.property,t,n),s.xProperty&&this.getDependencies(s.xProperty,t,n),s.yProperty&&this.getDependencies(s.yProperty,t,n),s.zProperty&&this.getDependencies(s.zProperty,t,n),t;case"SequenceExpression":return this.getDependencies(e.expressions,t,n);default:throw this.astErrorOutput(`Unhandled type ${e.type} in getDependencies`,e)}return t}getVariableSignature(e,t){if(!this.isAstVariable(e))throw new Error(`ast of type "${e.type}" is not a variable signature`);if("Identifier"===e.type)return"value";const n=[];for(;e;)e.computed?n.push("[]"):"ThisExpression"===e.type?n.unshift("this"):e.property&&e.property.name?"x"===e.property.name||"y"===e.property.name||"z"===e.property.name?n.unshift(t?"."+e.property.name:".value"):"constants"===e.property.name||"thread"===e.property.name||"output"===e.property.name?n.unshift("."+e.property.name):n.unshift(t?"."+e.property.name:".value"):e.name?n.unshift(t?e.name:"value"):e.callee&&e.callee.name?n.unshift(t?e.callee.name+"()":"fn()"):e.elements?n.unshift("[]"):n.unshift("unknown"),e=e.object;const r=n.join("");return t||p.includes(r)?r:null}build(){return this.toString().length>0}astGeneric(e,t){if(null===e)throw this.astErrorOutput("NULL ast",e);if(Array.isArray(e)){for(let n=0;n0?r[r.length-1]:0;return new Error(`${e} on line ${r.length}, position ${i.length}:\n ${n}`)}astDebuggerStatement(e,t){return t}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);return t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t}astFunction(e,t){throw new Error(`"astFunction" not defined on ${this.constructor.name}`)}astFunctionDeclaration(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}astFunctionExpression(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}isChildFunction(e){for(let t=0;t1?t.push("(",r.join(","),")"):t.push(r[0]),t}astUnaryExpression(e,t){if(this.checkAndUpconvertBitwiseUnary(e,t))return t;if(e.prefix){const n="-"===e.operator||"+"===e.operator;n&&t.push("("),t.push(e.operator),this.astGeneric(e.argument,t),n&&t.push(")")}else this.astGeneric(e.argument,t),t.push(e.operator);return t}checkAndUpconvertBitwiseUnary(e,t){}astUpdateExpression(e,t){return e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t}astLogicalExpression(e,t){return t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),t.push(")"),t}astMemberExpression(e,t){return t}astCallExpression(e,t){return t}astArrayExpression(e,t){return t}getMemberExpressionDetails(e){if("MemberExpression"!==e.type)throw this.astErrorOutput(`Expression ${e.type} not a MemberExpression`,e);let t=null,n=null;const r=this.getVariableSignature(e);switch(r){case"value":return null;case"value.thread.value":case"this.thread.value":case"this.output.value":return{signature:r,type:"Integer",name:e.property.name};case"value[]":if("string"!=typeof e.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object),xProperty:e.property};case"value[][]":if("string"!=typeof e.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object),yProperty:e.object.property,xProperty:e.property};case"value[][][]":if("string"!=typeof e.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value[][][][]":if("string"!=typeof e.object.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(this.isAstMathVariable(e))return t=e.property.name,{name:t,origin:"Math",type:"Number",signature:r};switch(e.property.name){case"r":case"g":case"b":case"a":return t=e.object.name,{name:t,property:e.property.name,origin:"user",signature:r,type:"Number"};default:throw this.astErrorOutput("Unexpected expression",e)}case"this.constants.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.property.name,n=this.getConstantType(t),!n)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:n,origin:"constants",signature:r};case"this.constants.value[]":if("string"!=typeof e.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.property.name,n=this.getConstantType(t),!n)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:n,origin:"constants",signature:r,xProperty:e.property};case"this.constants.value[][]":if("string"!=typeof e.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.property.name,n=this.getConstantType(t),!n)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:n,origin:"constants",signature:r,yProperty:e.object.property,xProperty:e.property};case"this.constants.value[][][]":if("string"!=typeof e.object.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.object.property.name,n=this.getConstantType(t),!n)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:n,origin:"constants",signature:r,zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"fn()[]":case"fn()[][]":case"[][]":return{signature:r,property:e.property};default:throw this.astErrorOutput("Unexpected expression",e)}}findIdentifierOrigin(e){const t=[this.ast];for(;t.length>0;){const n=t[0];if("VariableDeclarator"===n.type&&n.id&&n.id.name&&n.id.name===e.name)return n;if(t.shift(),n.argument)t.push(n.argument);else if(n.body)t.push(n.body);else if(n.declarations)t.push(n.declarations);else if(Array.isArray(n))for(let e=0;e0;){const e=t.pop();if("ReturnStatement"===e.type)return e;if("FunctionDeclaration"!==e.type)if(e.argument)t.push(e.argument);else if(e.body)t.push(e.body);else if(e.declarations)t.push(e.declarations);else if(Array.isArray(e))for(let n=0;n{const{FunctionNode:n}=h(),{threadLocalName:r}=o();t.exports={CPUFunctionNode:class extends n{get readsCanFault(){return!0}markupUserName(e){return this.isRootKernel&&this.getAssignedArguments().has(e)?`cellShadow_user_${e}`:`user_${e}`}astFunction(e,t){if(!this.isRootKernel){t.push("function"),t.push(" "),t.push(this.name),t.push("(");for(let e=0;e0&&t.push(", "),t.push("user_"),t.push(n)}t.push(") {\n")}if(this.isRootKernel){for(const e of this.getAssignedArguments())t.push(`let cellShadow_user_${e} = user_${e};\n`);t.push("kernelBody: {\n")}for(let n=0;n0&&t.push(n.join(""),";\n"),t.push(`for (let ${e}=0;${e}0&&t.push(`if (!${r.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);return t.push("for (let i = 0; i < LOOP_MAX; i++) {"),t.push("if ("),this.astGeneric(e.test,t),t.push(") {\n"),this.astGeneric(e.body,t),t.push("} else {\n"),t.push("break;\n"),t.push("}\n"),t.push("}\n"),t}astDoWhileStatement(e,t){if("DoWhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const n=`safeI${this.astKey(e,"_")}`;return t.push(`let ${n} = 0;\n`),t.push("do {"),this.astGeneric(e.body,t),t.push("} while (("),this.astGeneric(e.test,t),t.push(`) && ++${n} < LOOP_MAX);\n`),t}astAssignmentExpression(e,t){const n=this.isState("assignment-as-statement");return n?this.popState("assignment-as-statement"):t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),n||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let n=0;n0&&t.push(",");const r=n[e],s=this.getDeclaration(r.id);s.valueType||(s.valueType=this.getType(r.init)),this.astGeneric(r,t)}return this.isState("in-for-loop-init")||t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchStatement(e,t){const{discriminant:n,cases:r}=e;t.push("switch ("),this.astGeneric(n,t),t.push(") {\n");for(let e=0;e0&&(this.astGeneric(r[e].consequent,t),t.push("break;\n"))):(t.push("default:\n"),this.astGeneric(r[e].consequent,t),r[e].consequent&&r[e].consequent.length>0&&t.push("break;\n"));t.push("\n}")}astThisExpression(e,t){return t.push("_this"),t}astMemberExpression(e,t){const{signature:n,type:s,property:i,xProperty:a,yProperty:o,zProperty:u,name:l,origin:h}=this.getMemberExpressionDetails(e);switch(n){case"this.thread.value":{const e=r(this,l);return t.push(null===e?`_this.thread.${l}`:e),t}case"this.output.value":switch(l){case"x":t.push("outputX");break;case"y":t.push("outputY");break;case"z":t.push("outputZ");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":default:throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value.value":if("Math"===h)return t.push(Math[l]),t;switch(i){case"r":return t.push(`user_${l}[0]`),t;case"g":return t.push(`user_${l}[1]`),t;case"b":return t.push(`user_${l}[2]`),t;case"a":return t.push(`user_${l}[3]`),t}break;case"this.constants.value":case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":break;case"fn()[]":return this.astGeneric(e.object,t),t.push("["),this.astGeneric(e.property,t),t.push("]"),t;case"fn()[][]":return this.astGeneric(e.object.object,t),t.push("["),this.astGeneric(e.object.property,t),t.push("]"),t.push("["),this.astGeneric(e.property,t),t.push("]"),t}if(!e.computed)switch(s){case"Number":case"Integer":case"Float":case"Boolean":return t.push("user"===h?this.markupUserName(l):`${h}_${l}`),t}const c="user"===h?this.markupUserName(l):`${h}_${l}`;{let e,n;if("constants"===h){const t=this.constants[l];n="Input"===this.constantTypes[l],e=n?t.size:null}else n=this.isInput(l),e=n?this.argumentSizes[this.argumentNames.indexOf(l)]:null;t.push(`${c}`),u&&o?n?(t.push("[("),this.astGeneric(u,t),t.push(`*${this.dynamicArguments?"(outputY * outputX)":e[1]*e[0]})+(`),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(a,t),t.push("]")):(t.push("["),this.astGeneric(u,t),t.push("]"),t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]")):o?n?(t.push("[("),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(a,t),t.push("]")):(t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]")):void 0!==a&&(t.push("["),this.astGeneric(a,t),t.push("]"))}return t}astCallExpression(e,t){if("CallExpression"!==e.type)throw this.astErrorOutput("Unknown CallExpression",e);let n=this.astMemberExpressionUnroll(e.callee);this.calledFunctions.indexOf(n)<0&&this.calledFunctions.push(n),this.isAstMathFunction(e),this.onFunctionCall&&this.onFunctionCall(this.name,n,e.arguments),t.push(n),t.push("(");const r=this.lookupFunctionArgumentTypes(n)||[];for(let s=0;s0&&t.push(", "),this.astGeneric(i,t)}return t.push(")"),t}astArrayExpression(e,t){const n=this.getType(e),r=e.elements.length,s=[];for(let t=0;t{const{utils:n}=i();t.exports={cpuKernelString:function(e,t){const r=[],s=[],i=[],a=!/^function/.test(e.color.toString());if(r.push(" const { context, canvas, constants: incomingConstants } = settings;",` const output = new Int32Array(${JSON.stringify(Array.from(e.output))});`,` const _constantTypes = ${JSON.stringify(e.constantTypes)};`,` const _constants = ${function(e,t){const n=[];for(const r in t){if(!t.hasOwnProperty(r))continue;const s=t[r],i=e[r];switch(s){case"Number":case"Integer":case"Float":case"Boolean":n.push(`${r}:${i}`);break;case"Array(2)":case"Array(3)":case"Array(4)":case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":n.push(`${r}:new ${i.constructor.name}(${JSON.stringify(Array.from(i))})`)}}return`{ ${n.join()} }`}(e.constants,e.constantTypes)};`),s.push(" constants: _constants,"," context,"," output,"," thread: {x: 0, y: 0, z: 0},"),e.graphical){r.push(` const _imageData = context.createImageData(${e.output[0]}, ${e.output[1]});`),r.push(` const _colorData = new Uint8ClampedArray(${e.output[0]} * ${e.output[1]} * 4);`);const t=n.flattenFunctionToString((a?"function ":"")+e.color.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:(e,t)=>null}),o=n.flattenFunctionToString((a?"function ":"")+e.getPixels.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:()=>null});s.push(" _imageData,"," _colorData,",` color: ${t},`),i.push(` kernel.getPixels = ${o};`)}const o=[],u=Object.keys(e.constantTypes);for(let t=0;t"this"===t?(a?"function ":"")+e[n].toString():null,thisLookup:e=>{switch(e){case"canvas":return;case"context":return"context"}}});i.push(t),s.push(" _mediaTo2DArray,"),s.push(" _imageTo3DArray,")}else if(-1!==e.argumentTypes.indexOf("HTMLImage")||-1!==o.indexOf("HTMLImage")){const t=n.flattenFunctionToString((a?"function ":"")+e._mediaTo2DArray.toString(),{findDependency:(e,t)=>null,thisLookup:e=>{switch(e){case"canvas":return"settings.canvas";case"context":return"settings.context"}throw new Error("unhandled thisLookup")}});i.push(t),s.push(" _mediaTo2DArray,")}return`function(settings) {\n${r.join("\n")}\n for (const p in _constantTypes) {\n if (!_constantTypes.hasOwnProperty(p)) continue;\n const type = _constantTypes[p];\n switch (type) {\n case 'Number':\n case 'Integer':\n case 'Float':\n case 'Boolean':\n case 'Array(2)':\n case 'Array(3)':\n case 'Array(4)':\n case 'Matrix(2)':\n case 'Matrix(3)':\n case 'Matrix(4)':\n if (incomingConstants.hasOwnProperty(p)) {\n console.warn('constant ' + p + ' of type ' + type + ' cannot be resigned');\n }\n continue;\n }\n if (!incomingConstants.hasOwnProperty(p)) {\n throw new Error('constant ' + p + ' not found');\n }\n _constants[p] = incomingConstants[p];\n }\n const kernel = (function() {\n${e._kernelString}\n })\n .apply({ ${s.join("\n")} });\n ${i.join("\n")}\n return kernel;\n}`}}}),d=e((e,t)=>{const{Kernel:n}=a(),{FunctionBuilder:r}=u(),{CPUFunctionNode:s}=c(),{utils:o}=i(),{cpuKernelString:l}=p();t.exports={CPUKernel:class extends n{static getFeatures(){return this.features}static get features(){return Object.freeze({kernelMap:!0,isIntegerDivisionAccurate:!0})}static get isSupported(){return!0}static isContextMatch(e){return!1}static get mode(){return"cpu"}static nativeFunctionArguments(){return null}static nativeFunctionReturnType(){throw new Error(`Looking up native function return type not supported on ${this.name}`)}static combineKernels(e){return e}static getSignature(e,t){return"cpu"+(t.length>0?":"+t.join(","):"")}constructor(e,t){super(e,t),this._inliningDisabled=!0,this.mergeSettings(e.settings||t),this._imageData=null,this._colorData=null,this._kernelString=null,this._prependedString=[],this.thread={x:0,y:0,z:0},this.translatedSources=null}initCanvas(){return"undefined"!=typeof document?document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(0,0):void 0}initContext(){return this.canvas?this.canvas.getContext("2d",{willReadFrequently:!0}):null}initPlugins(e){return[]}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=o.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=o.getDimensions(t);else{if("NumberTexture"!==t&&"ArrayTexture(4)"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=e[0].output}}if(this.graphical&&2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");this.checkOutput()}translateSource(){if(this.leadingReturnStatement=this.output.length>1?"resultX[x] = ":"result[x] = ",this.subKernels){const e=[];for(let t=0;t1?`resultX_${n}[x] = subKernelResult_${n};\n`:`result_${n}[x] = subKernelResult_${n};\n`)}this.followingReturnStatement=e.join("")}const e=r.fromKernel(this,s);this.translatedSources=e.getPrototypes("kernel"),this.graphical||this.returnType||(this.returnType=e.getKernelResultType())}build(){if(this.built)return;if(null!==this.randomSeed&&console.warn("randomSeed is not supported in cpu mode; Math.random() will be unseeded"),this.setupConstants(),this.setupArguments(arguments),this.validateSettings(arguments),this.buildWithOptimizer(()=>this.translateSource()),this.graphical){const{canvas:e,output:t}=this;if(!e)throw new Error("no canvas available for using graphical output");const n=t[0],r=t[1]||1;e.width=n,e.height=r,this._imageData=this.context.createImageData(n,r),this._colorData=new Uint8ClampedArray(n*r*4)}const e=this.getKernelString();this.kernelString=e,this.debug&&(console.log("Function output:"),console.log(e));try{this.run=new Function([],e).bind(this)()}catch(e){console.error("An error occurred compiling the javascript: ",e)}this.buildSignature(arguments),this.built=!0}color(e,t,n,r){void 0===r&&(r=1),e=Math.floor(255*e),t=Math.floor(255*t),n=Math.floor(255*n),r=Math.floor(255*r);const s=this.output[0],i=this.output[1],a=this.thread.x+(i-this.thread.y-1)*s;this._colorData[4*a+0]=e,this._colorData[4*a+1]=t,this._colorData[4*a+2]=n,this._colorData[4*a+3]=r}getKernelString(){if(null!==this._kernelString)return this._kernelString;let e=null,{translatedSources:t}=this;return t.length>1?t=t.filter(t=>/^function/.test(t)?t:(e=t,!1)):e=t.shift(),this._kernelString=` const LOOP_MAX = ${this._getLoopMaxString()};\n ${this.injectedNative||""}\n const _this = this;\n ${this._resultKernelHeader()}\n ${this._processConstants()}\n return (${this.argumentNames.map(e=>"user_"+e).join(", ")}) => {\n ${this._prependedString.join("")}\n ${this._earlyThrows()}\n ${this._processArguments()}\n ${this.graphical?this._graphicalKernelBody(e):this._resultKernelBody(e)}\n ${t.length>0?t.join("\n"):""}\n };`}toString(){return l(this)}_getLoopMaxString(){return this.loopMaxIterations?` ${parseInt(this.loopMaxIterations)};`:" 1000;"}_processConstants(){if(!this.constants)return"";const e=[];for(let t in this.constants)switch(this.constantTypes[t]){case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":e.push(` const constants_${t} = this._mediaTo2DArray(this.constants.${t});\n`);break;case"HTMLImageArray":e.push(` const constants_${t} = this._imageTo3DArray(this.constants.${t});\n`);break;case"Input":e.push(` const constants_${t} = this.constants.${t}.value;\n`);break;default:e.push(` const constants_${t} = this.constants.${t};\n`)}return e.join("")}_earlyThrows(){if(this.graphical)return"";if(this.immutable)return"";if(!this.pipeline)return"";const e=[];for(let t=0;t`user_${r} === result_${e.name}`).join(" || ");t.push(`user_${r} === result${s?` || ${s}`:""}`)}return`if (${t.join(" || ")}) throw new Error('Source and destination arrays are the same. Use immutable = true');`}_processArguments(){const e=[];for(let t=0;t0?e.width:e.videoWidth,r=e.height>0?e.height:e.videoHeight;t.width=0;e--){const t=a[e]=new Array(n);for(let e=0;e`const result_${e.name} = new ${t}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_mutableKernel1DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const result = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const result_${t.name} = new ${e}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}`}_resultMutableKernel1DLoop(e){return` const outputX = _this.output[0];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_resultImmutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_mutableKernel2DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = result[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = result_${t.name}[y] = new ${e}(outputX);\n`).join("")}\n }`}_resultMutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y];\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_graphicalKernel2DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_resultImmutableKernel3DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = resultY_${e.name}[y] = new ${t}(outputX);\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_mutableKernel3DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = resultY[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = resultY_${t.name}[y] = new ${e}(outputX);\n`).join(" ")}\n }\n }`}_resultMutableKernel3DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z];\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_kernelOutput(){return this.subKernels?`\n return {\n result: result,\n ${this.subKernels.map(e=>`${e.property}: result_${e.name}`).join(",\n ")}\n };`:"\n return result;"}_mapSubKernels(e){return null===this.subKernels?[""]:this.subKernels.map(e)}destroy(e){e&&delete this.canvas}static destroyContext(e){}toJSON(){const e=super.toJSON();return e.functionNodes=r.fromKernel(this,s).toJSON(),e}setOutput(e){super.setOutput(e);const[t,n]=this.output;this.graphical&&(this._imageData=this.context.createImageData(t,n),this._colorData=new Uint8ClampedArray(t*n*4))}prependString(e){if(this._kernelString)throw new Error("Kernel already built");this._prependedString.push(e)}hasPrependString(e){return this._prependedString.indexOf(e)>-1}}}}),f=e((e,t)=>{const{Texture:n}=s();function r(e,t){e.activeTexture(e.TEXTURE15),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST)}t.exports={GLTexture:class extends n{get textureType(){throw new Error(`"textureType" not implemented on ${this.name}`)}clone(){return new this.constructor(this)}beforeMutate(){return this.texture._refs>1&&(this.newTexture(),!0)}cloneTexture(){this.texture._refs--;const{context:e,size:t,texture:n,kernel:s}=this;s.debug&&console.warn("cloning internal texture"),e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),r(e,n),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0);const i=e.createTexture();r(e,i),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t[0],t[1]),i._refs=1,this.texture=i}newTexture(){this.texture._refs--;const e=this.context,t=this.size;this.kernel.debug&&console.warn("new internal texture");const n=e.createTexture();r(e,n),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),n._refs=1,this.texture=n}clear(){if(this.texture._refs){this.texture._refs--;const e=this.context,t=this.texture=e.createTexture();r(e,t);const n=this.size;t._refs=1,e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,n[0],n[1],0,this.textureFormat,this.textureType,null)}const{context:e,texture:t}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.bindTexture(e.TEXTURE_2D,t),r(e,t),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}delete(){this._deleted||(this._deleted=!0,this.texture._refs&&(this.texture._refs--,this.texture._refs)||(this.kernel&&this.kernel.deleteTexture?this.kernel.deleteTexture(this.texture):this.context.deleteTexture(this.texture)))}framebuffer(){return this._framebuffer||(this._framebuffer=this.kernel.getRawValueFramebuffer(this.size[0],this.size[1])),this._framebuffer}}}}),m=e((e,t)=>{const{utils:n}=i(),{GLTexture:r}=f();t.exports={GLTextureFloat:class extends r{get textureType(){return this.context.FLOAT}constructor(e){super(e),this.type="ArrayTexture(1)"}renderRawOutput(){const e=this.context,t=this.size;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const n=new Float32Array(t[0]*t[1]*4);return e.readPixels(0,0,t[0],t[1],e.RGBA,e.FLOAT,n),n}renderValues(){return this._deleted?null:this.renderRawOutput()}toArray(){return n.erectFloat(this.renderValues(),this.output[0])}}}}),g=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return n.erectArray2(this.renderValues(),this.output[0],this.output[1])}}}}),y=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return n.erect2DArray2(this.renderValues(),this.output[0],this.output[1])}}}}),x=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return n.erect3DArray2(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),b=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return n.erectArray3(this.renderValues(),this.output[0])}}}}),v=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return n.erect2DArray3(this.renderValues(),this.output[0],this.output[1])}}}}),S=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return n.erect3DArray3(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),T=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return n.erectArray4(this.renderValues(),this.output[0])}}}}),A=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return n.erect2DArray4(this.renderValues(),this.output[0],this.output[1])}}}}),w=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return n.erect3DArray4(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),E=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureFloat2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return n.erect2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),I=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureFloat3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return n.erect3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),_=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return n.erectMemoryOptimizedFloat(this.renderValues(),this.output[0])}}}}),k=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized2D:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return n.erectMemoryOptimized2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),L=e((e,t)=>{const{utils:n}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized3D:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return n.erectMemoryOptimized3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),F=e((e,t)=>{const{utils:n}=i(),{GLTexture:r}=f();t.exports={GLTextureUnsigned:class extends r{get textureType(){return this.context.UNSIGNED_BYTE}constructor(e){super(e),this.type="NumberTexture"}renderRawOutput(){const{context:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const t=new Uint8Array(this.size[0]*this.size[1]*4);return e.readPixels(0,0,this.size[0],this.size[1],e.RGBA,e.UNSIGNED_BYTE,t),t}renderValues(){return this._deleted?null:new Float32Array(this.renderRawOutput().buffer)}toArray(){return n.erectPackedFloat(this.renderValues(),this.output[0])}}}}),D=e((e,t)=>{const{utils:n}=i(),{GLTextureUnsigned:r}=F();t.exports={GLTextureUnsigned2D:class extends r{constructor(e){super(e),this.type="NumberTexture"}toArray(){return n.erect2DPackedFloat(this.renderValues(),this.output[0],this.output[1])}}}}),$=e((e,t)=>{const{utils:n}=i(),{GLTextureUnsigned:r}=F();t.exports={GLTextureUnsigned3D:class extends r{constructor(e){super(e),this.type="NumberTexture"}toArray(){return n.erect3DPackedFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),C=e((e,t)=>{const{GLTextureUnsigned:n}=F();t.exports={GLTextureGraphical:class extends n{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return this.renderValues()}}}}),M=e((e,t)=>{const{Kernel:n}=a(),{utils:r}=i(),{GLTextureArray2Float:s}=g(),{GLTextureArray2Float2D:o}=y(),{GLTextureArray2Float3D:u}=x(),{GLTextureArray3Float:l}=b(),{GLTextureArray3Float2D:h}=v(),{GLTextureArray3Float3D:c}=S(),{GLTextureArray4Float:p}=T(),{GLTextureArray4Float2D:d}=A(),{GLTextureArray4Float3D:f}=w(),{GLTextureFloat:M}=m(),{GLTextureFloat2D:R}=E(),{GLTextureFloat3D:G}=I(),{GLTextureMemoryOptimized:N}=_(),{GLTextureMemoryOptimized2D:O}=k(),{GLTextureMemoryOptimized3D:z}=L(),{GLTextureUnsigned:V}=F(),{GLTextureUnsigned2D:B}=D(),{GLTextureUnsigned3D:U}=$(),{GLTextureGraphical:K}=C();const P={int:"Integer",float:"Number",vec2:"Array(2)",vec3:"Array(3)",vec4:"Array(4)"};t.exports={GLKernel:class extends n{static get mode(){return"gpu"}static getIsFloatRead(){const e=new this("function kernelFunction() {\n return 1;\n }",{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[1],precision:"single",returnType:"Number",tactic:"speed"});e.build(),e.run();const t=e.renderOutput();return e.destroy(!0),1===t[0]}static getIsIntegerDivisionAccurate(){const e=new this(function(e,t){return e[this.thread.x]/t[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[2],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[6,6030401],[3,3991]];e.build.apply(e,t),e.run.apply(e,t);const n=e.renderOutput();return e.destroy(!0),2===n[0]&&1511===n[1]}static getIsSpeedTacticSupported(){const e=new this(function(e){return e[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[4],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[0,1,2,3]];e.build.apply(e,t),e.run.apply(e,t);const n=e.renderOutput();return e.destroy(!0),0===Math.round(n[0])&&1===Math.round(n[1])&&2===Math.round(n[2])&&3===Math.round(n[3])}static get testCanvas(){throw new Error(`"testCanvas" not defined on ${this.name}`)}static get testContext(){throw new Error(`"testContext" not defined on ${this.name}`)}static getFeatures(){const e=this.testContext,t=this.getIsDrawBuffers();return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),isTextureFloat:this.getIsTextureFloat(),isDrawBuffers:t,kernelMap:t,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static setupFeatureChecks(){throw new Error(`"setupFeatureChecks" not defined on ${this.name}`)}static getSignature(e,t){return e.getVariablePrecisionString()+(t.length>0?":"+t.join(","):"")}setFixIntegerDivisionAccuracy(e){return this.fixIntegerDivisionAccuracy=e,this}setPrecision(e){return this.precision=e,this}setFloatTextures(e){return r.warnDeprecated("method","setFloatTextures","setOptimizeFloatMemory"),this.floatTextures=e,this}static nativeFunctionArguments(e){const t=[],n=[],r=[],s=/^[a-zA-Z_]/,i=/[a-zA-Z_0-9]/;let a=0,o=null,u=null;for(;a0?r[r.length-1]:null;if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"*"!==h)if("MULTI_LINE_COMMENT"!==c||"*"!==l||"/"!==h)if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"/"!==h)if("COMMENT"!==c||"\n"!==l)if(null!==c||"("!==l){if("FUNCTION_ARGUMENTS"===c){if(")"===l){r.pop();break}if("f"===l&&"l"===h&&"o"===e[a+2]&&"a"===e[a+3]&&"t"===e[a+4]&&" "===e[a+5]){r.push("DECLARE_VARIABLE"),u="float",o="",a+=6;continue}if("i"===l&&"n"===h&&"t"===e[a+2]&&" "===e[a+3]){r.push("DECLARE_VARIABLE"),u="int",o="",a+=4;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"2"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec2",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"3"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec3",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"4"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec4",o="",a+=5;continue}}else if("DECLARE_VARIABLE"===c){if(""===o){if(" "===l){a++;continue}if(!s.test(l))throw new Error("variable name is not expected string")}o+=l,i.test(h)||(r.pop(),n.push(o),t.push(P[u]))}a++}else r.push("FUNCTION_ARGUMENTS"),a++;else r.pop(),a++;else r.push("COMMENT"),a+=2;else r.pop(),a+=2;else r.push("MULTI_LINE_COMMENT"),a+=2}if(r.length>0)throw new Error("GLSL function was not parsable");return{argumentNames:n,argumentTypes:t}}static nativeFunctionReturnType(e){return P[e.match(/int|float|vec[2-4]/)[0]]}static combineKernels(e,t){e.apply(null,arguments);const{texSize:n,context:s,threadDim:i}=t.texSize;let a;if("single"===t.precision){const e=n[0],t=Math.ceil(n[1]/4);a=new Float32Array(e*t*4*4),s.readPixels(0,0,e,4*t,s.RGBA,s.FLOAT,a)}else{const e=new Uint8Array(n[0]*n[1]*4);s.readPixels(0,0,n[0],n[1],s.RGBA,s.UNSIGNED_BYTE,e),a=new Float32Array(e.buffer)}return a=a.subarray(0,i[0]*i[1]*i[2]),1===t.output.length?a:2===t.output.length?r.splitArray(a,t.output[0]):3===t.output.length?r.splitArray(a,t.output[0]*t.output[1]).map(function(e){return r.splitArray(e,t.output[0])}):void 0}constructor(e,t){super(e,t),this.transferValues=null,this.formatValues=null,this.TextureConstructor=null,this.renderOutput=null,this.renderRawOutput=null,this.texSize=null,this.translatedSource=null,this.compiledFragmentShader=null,this.compiledVertexShader=null,this.switchingKernels=null,this._textureSwitched=null,this._mappedTextureSwitched=null}checkTextureSize(){const{features:e}=this.constructor;if(this.texSize[0]>e.maxTextureSize||this.texSize[1]>e.maxTextureSize)throw new Error(`Texture size [${this.texSize[0]},${this.texSize[1]}] generated by kernel is larger than supported size [${e.maxTextureSize},${e.maxTextureSize}]`)}translateSource(){throw new Error(`"translateSource" not defined on ${this.constructor.name}`)}pickRenderStrategy(e){if(this.graphical)return this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=e=>e,this.TextureConstructor=K,null;if("unsigned"===this.precision)if(this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=this.readPackedPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=U,null):this.output[1]>0?(this.TextureConstructor=B,null):(this.TextureConstructor=V,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else switch(null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.renderOutput=this.renderValues,this.output[2]>0?(this.TextureConstructor=U,this.formatValues=r.erect3DPackedFloat,null):this.output[1]>0?(this.TextureConstructor=B,this.formatValues=r.erect2DPackedFloat,null):(this.TextureConstructor=V,this.formatValues=r.erectPackedFloat,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else{if("single"!==this.precision)throw new Error(`unhandled precision of "${this.precision}"`);if(this.renderRawOutput=this.readFloatPixelsToFloat32Array,this.transferValues=this.readFloatPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.optimizeFloatMemory?this.output[2]>0?(this.TextureConstructor=z,null):this.output[1]>0?(this.TextureConstructor=O,null):(this.TextureConstructor=N,null):this.output[2]>0?(this.TextureConstructor=G,null):this.output[1]>0?(this.TextureConstructor=R,null):(this.TextureConstructor=M,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,null):this.output[1]>0?(this.TextureConstructor=o,null):(this.TextureConstructor=s,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,null):this.output[1]>0?(this.TextureConstructor=h,null):(this.TextureConstructor=l,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,null):this.output[1]>0?(this.TextureConstructor=d,null):(this.TextureConstructor=p,null)}if(this.renderOutput=this.renderValues,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.optimizeFloatMemory)switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=z,this.formatValues=r.erectMemoryOptimized3DFloat,null):this.output[1]>0?(this.TextureConstructor=O,this.formatValues=r.erectMemoryOptimized2DFloat,null):(this.TextureConstructor=N,this.formatValues=r.erectMemoryOptimizedFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=r.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=r.erect2DArray2,null):(this.TextureConstructor=s,this.formatValues=r.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=r.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=r.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=r.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=r.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=r.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=r.erectArray4,null)}else switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=G,this.formatValues=r.erect3DFloat,null):this.output[1]>0?(this.TextureConstructor=R,this.formatValues=r.erect2DFloat,null):(this.TextureConstructor=M,this.formatValues=r.erectFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=r.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=r.erect2DArray2,null):(this.TextureConstructor=s,this.formatValues=r.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=r.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=r.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=r.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=r.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=r.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=r.erectArray4,null)}}throw new Error(`unhandled return type "${this.returnType}"`)}getKernelString(){throw new Error("abstract method call")}getMainResultTexture(){switch(this.returnType){case"LiteralInteger":case"Float":case"Integer":case"Number":return this.getMainResultNumberTexture();case"Array(2)":return this.getMainResultArray2Texture();case"Array(3)":return this.getMainResultArray3Texture();case"Array(4)":return this.getMainResultArray4Texture();default:throw new Error(`unhandled returnType type ${this.returnType}`)}}getMainResultKernelNumberTexture(){throw new Error("abstract method call")}getMainResultSubKernelNumberTexture(){throw new Error("abstract method call")}getMainResultKernelArray2Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray2Texture(){throw new Error("abstract method call")}getMainResultKernelArray3Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray3Texture(){throw new Error("abstract method call")}getMainResultKernelArray4Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray4Texture(){throw new Error("abstract method call")}getMainResultGraphical(){throw new Error("abstract method call")}getMainResultMemoryOptimizedFloats(){throw new Error("abstract method call")}getMainResultPackedPixels(){throw new Error("abstract method call")}getMainResultString(){return this.graphical?this.getMainResultGraphical():"single"===this.precision?this.optimizeFloatMemory?this.getMainResultMemoryOptimizedFloats():this.getMainResultTexture():this.getMainResultPackedPixels()}getMainResultNumberTexture(){return r.linesToString(this.getMainResultKernelNumberTexture())+r.linesToString(this.getMainResultSubKernelNumberTexture())}getMainResultArray2Texture(){return r.linesToString(this.getMainResultKernelArray2Texture())+r.linesToString(this.getMainResultSubKernelArray2Texture())}getMainResultArray3Texture(){return r.linesToString(this.getMainResultKernelArray3Texture())+r.linesToString(this.getMainResultSubKernelArray3Texture())}getMainResultArray4Texture(){return r.linesToString(this.getMainResultKernelArray4Texture())+r.linesToString(this.getMainResultSubKernelArray4Texture())}getFloatTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} float;\n`}getIntTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic,!0)} int;\n`}getSampler2DTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2D;\n`}getSampler2DArrayTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2DArray;\n`}renderTexture(){return this.immutable?this.texture.clone():this.texture}readPackedPixelsToUint8Array(){if("unsigned"!==this.precision)throw new Error('Requires this.precision to be "unsigned"');const{texSize:e,context:t}=this,n=new Uint8Array(e[0]*e[1]*4);return t.readPixels(0,0,e[0],e[1],t.RGBA,t.UNSIGNED_BYTE,n),n}readPackedPixelsToFloat32Array(){return new Float32Array(this.readPackedPixelsToUint8Array().buffer)}readFloatPixelsToFloat32Array(){if("single"!==this.precision)throw new Error('Requires this.precision to be "single"');const{texSize:e,context:t}=this,n=e[0],r=e[1],s=new Float32Array(n*r*4);return t.readPixels(0,0,n,r,t.RGBA,t.FLOAT,s),s}getPixels(e){const{context:t,output:n}=this,[s,i]=n,a=new Uint8Array(s*i*4);t.readPixels(0,0,s,i,t.RGBA,t.UNSIGNED_BYTE,a);const o=new Uint8ClampedArray((e?a:r.flipPixels(a,s,i)).buffer);return this.asyncMode?Promise.resolve(o):o}renderKernelsToArrays(){const e={result:this.renderOutput()};for(let t=0;t0){for(let e=0;e0){const{mappedTextures:n}=this;for(let r=0;r{const{utils:n}=i(),{FunctionNode:r}=h(),s={"<":"ceil",">=":"ceil",">":"floor","<=":"floor"};function a(e){if(!e||"object"!=typeof e)return!0;if(Array.isArray(e))return e.every(a);if("UpdateExpression"===e.type||"AssignmentExpression"===e.type||"SequenceExpression"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&!a(e[t]))return!1;return!0}function o(e){let t=!1;function n(e){if(!e||"object"!=typeof e||t)return!1;if(Array.isArray(e))return e.some(n);if("MemberExpression"===e.type&&e.computed)return!0;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&n(e[t]))return!0;return!1}return function e(r){if(r&&"object"==typeof r&&!t)if(Array.isArray(r))r.forEach(e);else if("MemberExpression"===r.type&&r.computed&&n(r.property))t=!0;else for(const t in r)"loc"!==t&&"range"!==t&&"parent"!==t&&e(r[t])}(e),t}function u(e,t){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>u(e,t));if("CallExpression"===e.type&&"Identifier"===e.callee.type&&e.callee.name===t)return!0;for(const n in e)if("loc"!==n&&"range"!==n&&"parent"!==n&&u(e[n],t))return!0;return!1}function l(e){let t=!1;return function e(n){if(n&&"object"==typeof n&&!t)if(Array.isArray(n))n.forEach(e);else if("CallExpression"===n.type&&"Identifier"===n.callee.type&&n.arguments.some(e=>u(e,n.callee.name)))t=!0;else for(const t in n)"loc"!==t&&"range"!==t&&"parent"!==t&&e(n[t])}(e),t}function c(e){const t="ExpressionStatement"===e.type&&"AssignmentExpression"===e.expression.type?e.expression:null;return function e(n){if(!n||"object"!=typeof n)return!0;if(Array.isArray(n))return n.every(e);if("string"==typeof n.type){if("UpdateExpression"===n.type||"SequenceExpression"===n.type)return!1;if("AssignmentExpression"===n.type&&n!==t)return!1}for(const t in n)if("loc"!==t&&"range"!==t&&"parent"!==t&&!e(n[t]))return!1;return!0}(e)}const p={"Matrix(2)":2,"Matrix(3)":3,"Matrix(4)":4},d={Array:"sampler2D","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4","Matrix(2)":"mat2","Matrix(3)":"mat3","Matrix(4)":"mat4",Array2D:"sampler2D",Array3D:"sampler2D",Boolean:"bool",Float:"float",Input:"sampler2D",Integer:"int",Number:"float",LiteralInteger:"float",NumberTexture:"sampler2D",MemoryOptimizedNumberTexture:"sampler2D","ArrayTexture(1)":"sampler2D","ArrayTexture(2)":"sampler2D","ArrayTexture(3)":"sampler2D","ArrayTexture(4)":"sampler2D",HTMLVideo:"sampler2D",HTMLCanvas:"sampler2D",OffscreenCanvas:"sampler2D",HTMLImage:"sampler2D",ImageBitmap:"sampler2D",ImageData:"sampler2D",HTMLImageArray:"sampler2DArray"},f={"===":"==","!==":"!="};function m(e){return!!e&&("UnaryExpression"!==e.type||"-"!==e.operator&&"+"!==e.operator?"Literal"===e.type&&"number"==typeof e.value&&!Number.isInteger(e.value):m(e.argument))}t.exports={WebGLFunctionNode:class extends r{constructor(e,t){super(e,t),t&&t.hasOwnProperty("fixIntegerDivisionAccuracy")&&(this.fixIntegerDivisionAccuracy=t.fixIntegerDivisionAccuracy)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const n=this.getType(e.consequent),r=this.getType(e.alternate);return null===n&&null===r?(t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t):(t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t)}astFunction(e,t){if(this.isRootKernel)t.push("void");else{this.returnType||this.findLastReturn()&&(this.returnType=this.getType(e.body),"LiteralInteger"===this.returnType&&(this.returnType="Number"));const{returnType:n}=this;if(n){const e=d[n];if(!e)throw new Error(`unknown type ${n}`);t.push(e)}else t.push("void")}if(t.push(" "),t.push(this.name),t.push("("),!this.isRootKernel)for(let r=0;r0&&t.push(", ");let i=this.argumentTypes[this.argumentNames.indexOf(s)];if(!i)throw this.astErrorOutput(`Unknown argument ${s} type`,e);"LiteralInteger"===i&&(this.argumentTypes[r]=i="Number");const a=d[i];if(!a)throw this.astErrorOutput("Unexpected expression",e);const o=n.sanitizeName(s);"sampler2D"===a||"sampler2DArray"===a?t.push(`${a} user_${o},ivec2 user_${o}Size,ivec3 user_${o}Dim`):t.push(`${a} user_${o}`)}if(t.push(") {\n"),this.isRootKernel){const e=this.getAssignedArguments();for(let r=0;r>":"bitwiseSignedRightShift",">>>":"bitwiseZeroFillRightShift"}[e.operator];if(!n)return null;switch(t.push(n),t.push("("),this.getType(e.left)){case"Number":case"Float":this.castValueToInteger(e.left,t);break;case"LiteralInteger":this.castLiteralToInteger(e.left,t);break;default:this.astGeneric(e.left,t)}switch(t.push(","),this.getType(e.right)){case"Number":case"Float":this.castValueToInteger(e.right,t);break;case"LiteralInteger":this.castLiteralToInteger(e.right,t);break;default:this.astGeneric(e.right,t)}return t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){const n={"~":"bitwiseNot"}[e.operator];if(!n)return null;switch(t.push(n),t.push("("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("int("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("float("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),s=n.sanitizeName(e.name);if("Infinity"===e.name)t.push("3.402823466e+38");else if("Boolean"===r)if(this.argumentNames.indexOf(s)>-1){const n=this.markupUserName(e.name);t.push(n.startsWith("cellShadow_")?n:`bool(${n})`)}else t.push(`user_${s}`);else t.push(this.markupUserName(e.name));return t}markupUserName(e){const t=n.sanitizeName(e);if(this.isRootKernel&&this.getAssignedArguments().has(e)){const n=this.argumentNames.indexOf(e),r=-1===n?null:d[this.argumentTypes[n]];if("float"===r||"int"===r||"bool"===r)return`cellShadow_user_${t}`}return`user_${t}`}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const n=[],r=[],s=[],i=[];let a=null;if(e.init)if("VariableDeclaration"!==e.init.type)a=!1,this.astGeneric(e.init,n),n.push(";");else{const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,n);for(let e=0;e{const t=this.getDeclaration(e);return null!==t&&n.has(t)},a=e=>{if(e&&"object"==typeof e&&!s)if(Array.isArray(e))for(const t of e)a(t);else if("ForStatement"!==e.type||!e.init||"VariableDeclaration"!==e.init.type||!e.init.declarations.some(e=>e.id&&"Identifier"===e.id.type&&r.has(e.id.name)))if("AssignmentExpression"===e.type&&"Identifier"===e.left.type&&i(e.left))s=!0;else if("UpdateExpression"===e.type&&"Identifier"===e.argument.type&&i(e.argument))s=!0;else for(const t in e){if("loc"===t||"range"===t||"parent"===t)continue;const n=e[t];n&&"object"==typeof n&&a(n)}};return a(e.body),!s&&e.test&&a(e.test),s}emitForParts(e,t){const{initArr:n,testArr:r,updateArr:s,bodyArr:i,isSafe:a}=e;if(a){const e=n.join(""),a=";"!==e[e.length-1];t.push(`for (${e}${a?";":""}${r.join("")};${s.join("")}){\n`),t.push(i.join("")),t.push("}\n")}else{const e=this.getInternalVariableName("safeI");n.length>0&&t.push(n.join(""),"\n"),t.push(`for (int ${e}=0;${e}0&&t.push(`if (!${r.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const n=this.getInternalVariableName("safeI");return t.push(`for (int ${n}=0;${n}0){if (!`),this.astGeneric(e.test,t),t.push(") break;}\n"),this.astGeneric(e.body,t),t.push("}\n"),t}astAssignmentExpression(e,t){const n=this.isState("assignment-as-statement");if(n?this.popState("assignment-as-statement"):t.push("("),"%="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("mod("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else if("**="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("pow("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else{const n=this.getType(e.left),r=this.getType(e.right);this.astGeneric(e.left,t),t.push(e.operator),"Integer"!==n&&"Integer"===r?(t.push("float("),this.astGeneric(e.right,t),t.push(")")):"Integer"===n&&"LiteralInteger"===r?this.castLiteralToInteger(e.right,t):this.astGeneric(e.right,t)}return n||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let n=0;nnull!==e&&(o(e)||l(e))))return null;const i=e=>JSON.parse(JSON.stringify(e)),a=e=>({type:"IfStatement",test:{type:"UnaryExpression",operator:"!",prefix:!0,argument:e},consequent:{type:"BlockStatement",body:[{type:"BreakStatement",label:null}]},alternate:null}),u=e=>"VariableDeclaration"===e.type?e:{type:"ExpressionStatement",expression:e},h="BlockStatement"===e.body.type?e.body.body.slice():[e.body],c=(e,t)=>{const n=e=>{if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(n);switch(e.type){case"ContinueStatement":return{type:"BlockStatement",body:[...t(),e]};case"ForStatement":case"WhileStatement":case"DoWhileStatement":default:return e;case"IfStatement":return{...e,consequent:n(e.consequent),alternate:n(e.alternate)};case"BlockStatement":return{...e,body:e.body.map(n)};case"SwitchStatement":return{...e,cases:e.cases.map(e=>({...e,consequent:e.consequent.map(n)}))}}};return e.map(n)},p=[];"DoWhileStatement"===t?(p.push(...r?c(h,()=>[a(i(r))]):h),r&&p.push(a(r))):(r&&p.push(a(r)),p.push(...s?c(h,()=>[u(i(s))]):h),s&&p.push(u(s)));const d={type:"BlockStatement",body:[...n?[u(n)]:[],{type:"WhileStatement",test:{type:"Literal",value:!0,raw:"true"},body:{type:"BlockStatement",body:p}}]};return this.stampSyntheticNodes(d),d}stampSyntheticNodes(e){let t=this.syntheticNodeId||1073741824;const n=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(n);else{"string"==typeof e.type&&void 0===e.start&&(e.start=t,e.end=t+1,t+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&n(e[t])}};n(e),this.syntheticNodeId=t}linearizeStatement(e){const t=[];let n=!1,r=this.linearTempId||0;const s=e=>({type:"Identifier",name:e}),i=(e,t,n)=>({type:"VariableDeclaration",kind:e,declarations:[{type:"VariableDeclarator",id:s(t),init:n}]}),o=(e,t)=>{const n="hoistSeq"+r++;return e.push(i("const",n,t)),s(n)},l=e=>!a(e),h=(e,t)=>{if(n||!e||"object"!=typeof e)return e;switch(e.type){case"Identifier":case"Literal":case"ThisExpression":return e;case"MemberExpression":{const n=h(e.object,t),r=e.computed?h(e.property,t):e.property;return{...e,object:n,property:r}}case"CallExpression":{const n=e.arguments.map(e=>h(e,t));if("Identifier"===e.callee.type)for(let r=0;rh(e,t))};case"UpdateExpression":{if("Identifier"!==e.argument.type)return n=!0,e;if(e.prefix)return t.push({type:"ExpressionStatement",expression:e}),o(t,e.argument);const r=o(t,e.argument);return t.push({type:"ExpressionStatement",expression:e}),r}case"AssignmentExpression":{if("Identifier"!==e.left.type)return n=!0,e;const r=h(e.right,t);return t.push({type:"ExpressionStatement",expression:{...e,right:r}}),o(t,e.left)}case"SequenceExpression":for(let n=0;n({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:s(e),right:t}});return o.push(d(a,c)),u.push(d(a,p)),t.push({type:"IfStatement",test:n,consequent:{type:"BlockStatement",body:o},alternate:{type:"BlockStatement",body:u}}),s(a)}case"LogicalExpression":{if(!l(e.right))return{...e,left:h(e.left,t)};const n=h(e.left,t),a="hoistSeq"+r++;t.push(i("let",a,n));const o=[],u=h(e.right,o);return o.push({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:s(a),right:u}}),t.push({type:"IfStatement",test:"&&"===e.operator?s(a):{type:"UnaryExpression",operator:"!",prefix:!0,argument:s(a)},consequent:{type:"BlockStatement",body:o},alternate:null}),s(a)}default:return n=!0,e}};switch(e.type){case"ExpressionStatement":{const n=e.expression;if("AssignmentExpression"===n.type&&"Identifier"===n.left.type){const e=h(n.right,t);t.push({type:"ExpressionStatement",expression:{...n,right:e}})}else{const e=h(n,t);"UpdateExpression"!==e.type&&"AssignmentExpression"!==e.type||t.push({type:"ExpressionStatement",expression:e})}break}case"VariableDeclaration":for(let n=0;n{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(p);else{"string"==typeof e.type&&void 0===e.start&&(e.start=c,e.end=c+1,c+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&p(e[t])}};return p(t),this.syntheticNodeId=c,t}astStatementWithHoisting(e,t){switch(e.type){case"ExpressionStatement":case"VariableDeclaration":case"ReturnStatement":{if(!c(e))return this.astGeneric(e,t);const n=this.hoistedIndexReads,r=this.hoistedIndexReads=[],s=[];return this.astGeneric(e,s),this.hoistedIndexReads=n,t.push(...r,...s),t}default:return this.astGeneric(e,t)}}astVariableDeclaration(e,t){const r=e.declarations;if(!r||!r[0]||!r[0].init)throw this.astErrorOutput("Unexpected expression",e);const s=[];let i=null;const a=[];let o=[];for(let t=0;t0&&a.push(o.join(",")),s.push(a.join(";")),t.push(s.join("")),t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchCaseConsequent(e,t){const n=[];for(let t=0;t{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const n in e)if("loc"!==n&&"range"!==n&&"parent"!==n&&t(e[n]))return!0;return!1};if(t(n[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",n[e])}for(let e=0;en+1){l=!0,this.astSwitchCaseConsequent(r[n].consequent,u);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(r[n].consequent,t),t.push("\n}")}return l&&(t.push(" else {"),t.push(u.join("")),t.push("}")),t}astThisExpression(e,t){return t.push("this"),t}astMemberExpression(e,t){const{property:r,name:s,signature:i,origin:a,type:o,xProperty:u,yProperty:l,zProperty:h}=this.getMemberExpressionDetails(e);switch(i){case"value.thread.value":case"this.thread.value":if("x"!==s&&"y"!==s&&"z"!==s)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`threadId.${s}`),t;case"this.output.value":if(this.dynamicOutput)switch(s){case"x":this.isState("casting-to-float")?t.push("float(uOutputDim.x)"):t.push("uOutputDim.x");break;case"y":this.isState("casting-to-float")?t.push("float(uOutputDim.y)"):t.push("uOutputDim.y");break;case"z":this.isState("casting-to-float")?t.push("float(uOutputDim.z)"):t.push("uOutputDim.z");break;default:throw this.astErrorOutput("Unexpected expression",e)}else switch(s){case"x":this.isState("casting-to-integer")?t.push(this.output[0]):t.push(this.output[0],".0");break;case"y":this.isState("casting-to-integer")?t.push(this.output[1]):t.push(this.output[1],".0");break;case"z":this.isState("casting-to-integer")?t.push(this.output[2]):t.push(this.output[2],".0");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===a)return t.push(Math[s]),t;const i=n.sanitizeName(s);switch(r){case"r":return t.push(`user_${i}.r`),t;case"g":return t.push(`user_${i}.g`),t;case"b":return t.push(`user_${i}.b`),t;case"a":return t.push(`user_${i}.a`),t}break;case"this.constants.value":if(void 0===u)switch(o){case"Array(2)":case"Array(3)":case"Array(4)":return t.push(`constants_${n.sanitizeName(s)}`),t}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":break;case"fn()[]":return this.astCallExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t;case"fn()[][]":{const n=e.object.property,r=e.property,s=p[this.getType(e.object.object)],i=e=>"LiteralInteger"===this.getType(e);return!s||i(n)&&i(r)?(this.astCallExpression(e.object.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(n)),t.push("]"),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t):(t.push(`getMatrix${s}(`),this.astCallExpression(e.object.object,t),t.push(", "),t.push(this.memberExpressionPropertyMarkup(n)),t.push(", "),t.push(this.memberExpressionPropertyMarkup(r)),t.push(")"),t)}case"[][]":return this.astArrayExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t;default:throw this.astErrorOutput("Unexpected expression",e)}if(!1===e.computed)switch(o){case"Number":case"Integer":case"Float":case"Boolean":return t.push(`${a}_${n.sanitizeName(s)}`),t}const c=`${a}_${n.sanitizeName(s)}`;switch(o){case"Array(2)":case"Array(3)":case"Array(4)":this.astGeneric(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(u)),t.push("]");break;case"HTMLImageArray":t.push(`getImage3D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(1)":t.push(`getFloatFromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(2)":case"Array2D(2)":case"Array3D(2)":t.push(`getMemoryOptimizedVec2(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(2)":t.push(`getVec2FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(3)":case"Array2D(3)":case"Array3D(3)":t.push(`getMemoryOptimizedVec3(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(3)":t.push(`getVec3FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(4)":case"Array2D(4)":case"Array3D(4)":t.push(`getMemoryOptimizedVec4(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(4)":case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":t.push(`getVec4FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"NumberTexture":case"Array":case"Array2D":case"Array3D":case"Array4D":case"Input":case"Number":case"Float":case"Integer":if("single"===this.precision)t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");else{const e="user"===a?this.lookupFunctionArgumentBitRatio(this.name,s):this.constantBitRatios[s];switch(e){case 1:t.push(`get8(${c}, ${c}Size, ${c}Dim, `);break;case 2:t.push(`get16(${c}, ${c}Size, ${c}Dim, `);break;case 4:case 0:t.push(`get32(${c}, ${c}Size, ${c}Dim, `);break;default:throw new Error(`unhandled bit ratio of ${e}`)}this.memberExpressionXYZ(u,l,h,t),t.push(")")}break;case"MemoryOptimizedNumberTexture":t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`${c}[${this.memberExpressionPropertyMarkup(l)}]`),l&&t.push(`[${this.memberExpressionPropertyMarkup(u)}]`);break;default:throw new Error(`unhandled member expression "${o}"`)}return t}astCallExpression(e,t){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);let r=null;const s=this.isAstMathFunction(e);if(r=s||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!r)throw this.astErrorOutput("Unhandled function, couldn't find name",e);switch(r){case"pow":r="_pow";break;case"round":r="_round"}if(this.calledFunctions.indexOf(r)<0&&this.calledFunctions.push(r),"random"===r&&this.plugins&&this.plugins.length>0)for(let e=0;e0&&t.push(", "),"Integer"===s)this.castValueToFloat(r,t);else this.astGeneric(r,t)}else{const s=this.lookupFunctionArgumentTypes(r)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(r,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("int("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("float("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.pushState("building-integer"),this.astGeneric(a,t),this.popState("building-integer");continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){if("Identifier"===a.type)t.push(`user_${n.sanitizeName(a.name)}`);else{if("ArrayExpression"!==a.type&&"MemberExpression"!==a.type&&"CallExpression"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.astGeneric(a,t)}continue}break;case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLImageArray":case"HTMLVideo":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":case"Array":case"Input":if(o===u){if("Identifier"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.triggerImplyArgumentBitRatio(this.name,a.name,r,i);const s=n.sanitizeName(a.name);t.push(`user_${s},user_${s}Size,user_${s}Dim`);continue}}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),t}astArrayExpression(e,t){const n=this.getType(e),r=e.elements.length;switch(n){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`mat${r}(`);break;default:t.push(`vec${r}(`)}for(let n=0;n0&&t.push(", ");const r=e.elements[n];this.astGeneric(r,t)}return t.push(")"),t}memberExpressionXYZ(e,t,n,r){return n?r.push(this.memberExpressionPropertyMarkup(n),", "):r.push("0, "),t?r.push(this.memberExpressionPropertyMarkup(t),", "):r.push("0, "),r.push(this.memberExpressionPropertyMarkup(e)),r}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer");break;default:this.astGeneric(e,t)}const r=t.join("");if(this.hoistedIndexReads&&/\b\w+\((user_|constants_)\w+, \1\w+Size/.test(r)){const e=`hoisted_${this.hoistedIndexReads.length}_${n.sanitizeName(this.name)}`,t=r.startsWith("int(");return this.hoistedIndexReads.push(`${t?"int":"float"} ${e}=${r};\n`),e}return r}}}}),G=e((e,t)=>{t.exports={name:"math-random-uniformly-distributed",onBeforeRun:e=>{if(null===e.randomSeed||void 0===e.randomSeed)return e.setUniform1f("randomSeed1",Math.random()),void e.setUniform1f("randomSeed2",Math.random());e._mathRandomGenerator&&e._mathRandomGeneratorSeed===e.randomSeed||(e._mathRandomGenerator=function(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(e.randomSeed),e._mathRandomGeneratorSeed=e.randomSeed),e.setUniform1f("randomSeed1",e._mathRandomGenerator()),e.setUniform1f("randomSeed2",e._mathRandomGenerator())},functionMatch:"Math.random()",functionReplace:"nrand(vTexCoord)",functionReturnType:"Number",source:"// https://www.shadertoy.com/view/4t2SDh\n//note: uniformly distributed, normalized rand, [0,1]\nhighp float randomSeedShift = 1.0;\nhighp float slide = 1.0;\nuniform highp float randomSeed1;\nuniform highp float randomSeed2;\n\nhighp float nrand(highp vec2 n) {\n highp float result = fract(sin(dot((n.xy + 1.0) * vec2(randomSeed1 * slide, randomSeed2 * randomSeedShift), vec2(12.9898, 78.233))) * 43758.5453);\n randomSeedShift = result;\n if (randomSeedShift > 0.5) {\n slide += 0.00009; \n } else {\n slide += 0.0009;\n }\n return result;\n}"}}),N=e((e,t)=>{t.exports={fragmentShader:`__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nvarying vec2 vTexCoord;\n\nfloat acosh(float x) {\n return log(x + sqrt(x * x - 1.0));\n}\n\nfloat sinh(float x) {\n return (pow(${Math.E}, x) - pow(${Math.E}, -x)) / 2.0;\n}\n\nfloat asinh(float x) {\n return log(x + sqrt(x * x + 1.0));\n}\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat atanh(float x) {\n x = (x + 1.0) / (x - 1.0);\n if (x < 0.0) {\n return 0.5 * log(-x);\n }\n return 0.5 * log(x);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat cosh(float x) {\n return (pow(${Math.E}, x) + pow(${Math.E}, -x)) / 2.0; \n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat tanh(float x) {\n float e = exp(2.0 * x);\n return (e - 1.0) / (e + 1.0);\n}\n\nfloat trunc(float x) {\n if (x >= 0.0) {\n return floor(x); \n } else {\n return ceil(x);\n }\n}\n\nvec4 _round(vec4 x) {\n return floor(x + 0.5);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x / y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(_round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(_round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;\n if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;\n return 0.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n if (channel == 0) return texel.r * 255.0;\n if (channel == 1) return texel.g * 255.0;\n if (channel == 2) return texel.b * 255.0;\n if (channel == 3) return texel.a * 255.0;\n return 0.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return texel.r;\n if (channel == 1) return texel.g;\n if (channel == 2) return texel.b;\n if (channel == 3) return texel.a;\n return 0.0;\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture2D(tex, st / vec2(texSize));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n \n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nvoid color(sampler2D image) {\n actualColor = texture2D(image, vTexCoord);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),O=e((e,t)=>{t.exports={vertexShader:"__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nattribute vec2 aPos;\nattribute vec2 aTexCoord;\n\nvarying vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),z=e((e,t)=>{function n(e,t={}){const{contextName:n="gl",throwGetError:a,useTrackablePrimitives:o,recording:u=[],variables:l={},onReadPixels:h,onUnrecognizedArgumentLookup:c}=t,p=new Proxy(e,{get:function(t,p){switch(p){case"addComment":return A;case"checkThrowError":return w;case"getReadPixelsVariableName":return m;case"insertVariable":return b;case"reset":return x;case"setIndent":return S;case"toString":return y;case"getContextVariableName":return I}return"function"==typeof e[p]?function(){switch(p){case"getError":return a?u.push(`${g}if (${n}.getError() !== ${n}.NONE) throw new Error('error');`):u.push(`${g}${n}.getError();`),e.getError();case"getExtension":{const t=`${n}Variables${d.length}`;u.push(`${g}const ${t} = ${n}.getExtension('${arguments[0]}');`);const s=e.getExtension(arguments[0]);if(s&&"object"==typeof s){const e=r(s,{getEntity:v,useTrackablePrimitives:o,recording:u,contextName:t,contextVariables:d,variables:l,indent:g,onUnrecognizedArgumentLookup:c});return d.push(e),e}return d.push(null),s}case"readPixels":const t=d.indexOf(arguments[6]);let i;if(-1===t){const e=function(e){if(l)for(const t in l)if(l[t]===e)return t;return null}(arguments[6]);e?(i=e,u.push(`${g}${e}`)):(i=`${n}Variable${d.length}`,d.push(arguments[6]),u.push(`${g}const ${i} = new ${arguments[6].constructor.name}(${arguments[6].length});`))}else i=`${n}Variable${t}`;m=i;const p=[arguments[0],arguments[1],arguments[2],arguments[3],v(arguments[4]),v(arguments[5]),i];return u.push(`${g}${n}.readPixels(${p.join(", ")});`),h&&h(i,p),e.readPixels.apply(e,arguments);case"drawBuffers":return u.push(`${g}${n}.drawBuffers([${s(arguments[0],{contextName:n,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})}]);`),e.drawBuffers(arguments[0])}let t=e[p].apply(e,arguments);switch(typeof t){case"undefined":return void u.push(`${g}${E(p,arguments)};`);case"number":case"boolean":if(o&&-1===d.indexOf(i(t))){u.push(`${g}const ${n}Variable${d.length} = ${E(p,arguments)};`),d.push(t=i(t));break}default:null===t?u.push(`${E(p,arguments)};`):u.push(`${g}const ${n}Variable${d.length} = ${E(p,arguments)};`),d.push(t)}return t}:(f[e[p]]=p,e[p])}}),d=[],f={};let m,g="";return p;function y(){return u.join("\n")}function x(){for(;u.length>0;)u.pop()}function b(e,t){l[e]=t}function v(e){const t=f[e];return t?n+"."+t:e}function S(e){g=" ".repeat(e)}function T(e,t){const r=`${n}Variable${d.length}`;return u.push(`${g}const ${r} = ${t};`),d.push(e),r}function A(e){u.push(`${g}// ${e}`)}function w(){u.push(`${g}(() => {\n${g}const error = ${n}.getError();\n${g}if (error !== ${n}.NONE) {\n${g} const names = Object.getOwnPropertyNames(gl);\n${g} for (let i = 0; i < names.length; i++) {\n${g} const name = names[i];\n${g} if (${n}[name] === error) {\n${g} throw new Error('${n} threw ' + name);\n${g} }\n${g} }\n${g}}\n${g}})();`)}function E(e,t){return`${n}.${e}(${s(t,{contextName:n,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})})`}function I(e){const t=d.indexOf(e);return-1!==t?`${n}Variable${t}`:null}}function r(e,t){const n=new Proxy(e,{get:function(t,n){return"function"==typeof t[n]?function(){if("drawBuffersWEBGL"===n)return h.push(`${p}${a}.drawBuffersWEBGL([${s(arguments[0],{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})}]);`),e.drawBuffersWEBGL(arguments[0]);let t=e[n].apply(e,arguments);switch(typeof t){case"undefined":return void h.push(`${p}${m(n,arguments)};`);case"number":case"boolean":l&&-1===o.indexOf(i(t))?(h.push(`${p}const ${a}Variable${o.length} = ${m(n,arguments)};`),o.push(t=i(t))):(h.push(`${p}const ${a}Variable${o.length} = ${m(n,arguments)};`),o.push(t));break;default:null===t?h.push(`${m(n,arguments)};`):h.push(`${p}const ${a}Variable${o.length} = ${m(n,arguments)};`),o.push(t)}return t}:(r[e[n]]=n,e[n])}}),r={},{contextName:a,contextVariables:o,getEntity:u,useTrackablePrimitives:l,recording:h,variables:c,indent:p,onUnrecognizedArgumentLookup:d}=t;return n;function f(e){return r.hasOwnProperty(e)?`${a}.${r[e]}`:u(e)}function m(e,t){return`${a}.${e}(${s(t,{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})})`}function g(e,t){const n=`${a}Variable${o.length}`;return o.push(e),h.push(`${p}const ${n} = ${t};`),n}}function s(e,t){const{variables:n,onUnrecognizedArgumentLookup:r}=t;return Array.from(e).map(e=>{const s=function(e){if(n)for(const t in n)if(n.hasOwnProperty(t)&&n[t]===e)return t;return r?r(e):null}(e);return s||function(e,t){const{contextName:n,contextVariables:r,getEntity:s,addVariable:i,onUnrecognizedArgumentLookup:a}=t;if(void 0===e)return"undefined";if(null===e)return"null";const o=r.indexOf(e);if(o>-1)return`${n}Variable${o}`;switch(e.constructor.name){case"String":const t=/\n/.test(e),n=/'/.test(e),r=/"/.test(e);return t?"`"+e+"`":n&&!r?'"'+e+'"':"'"+e+"'";case"Number":case"Boolean":return s(e);case"Array":return i(e,`new ${e.constructor.name}([${Array.from(e).join(",")}])`);case"Float32Array":case"Uint8Array":case"Uint16Array":case"Int32Array":return i(e,`new ${e.constructor.name}(${JSON.stringify(Array.from(e))})`);default:if(a){const t=a(e);if(t)return t}throw new Error(`unrecognized argument type ${e.constructor.name}`)}}(e,t)}).join(", ")}function i(e){return new e.constructor(e)}void 0!==t&&(t.exports={glWiretap:n,glExtensionWiretap:r}),"undefined"!=typeof window&&(n.glExtensionWiretap=r,window.glWiretap=n)}),V=e((e,t)=>{const{glWiretap:n}=z(),{utils:r}=i();function s(e){let t=e.toString().replace(/^function /,"");const n=t.indexOf("=>");if(-1!==n&&!/[{]|\bfunction\b/.test(t.slice(0,n))){const e=t.slice(0,n).trim(),r=t.slice(n+2).trim();t=r.startsWith("{")?`${e} ${r}`:`${e} { return ${r}; }`}return t.replace(/utils[.]/g,"/*utils.*/")}function a(e,t){const n="single"===t.precision?e:`new Float32Array(${e}.buffer)`;return t.output[2]?`renderOutput(${n}, ${t.output[0]}, ${t.output[1]}, ${t.output[2]})`:t.output[1]?`renderOutput(${n}, ${t.output[0]}, ${t.output[1]})`:`renderOutput(${n}, ${t.output[0]})`}function o(e,t){const n=e.toArray.toString(),s=!/^function/.test(n);return`() => {\n function framebuffer() { return getReadFramebuffer(); };\n ${r.flattenFunctionToString(`${s?"function ":""}${n}`,{findDependency:(t,n)=>{if("utils"===t)return`const ${n} = ${r[n].toString()};`;if("this"===t)return"framebuffer"===n?"":`${s?"function ":""}${e[n].toString()}`;throw new Error("unhandled fromObject")},thisLookup:(n,r)=>{if("texture"===n)return t;if("context"===n)return r?null:"gl";if(e.hasOwnProperty(n))return JSON.stringify(e[n]);throw new Error(`unhandled thisLookup ${n}`)}})}\n return toArray();\n }`}function u(e,t,n,r,s){if(null===e)return null;if(null===t)return null;switch(typeof e){case"boolean":case"number":return null}if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement)for(let s=0;s{switch(typeof e){case"boolean":return new Boolean(e);case"number":return new Number(e);default:return e}}):null;const c=[],p=[],d=n(i.context,{useTrackablePrimitives:!0,onReadPixels:e=>{if(R.subKernels){if(f){const t=R.subKernels[m++].property;p.push(` result${isNaN(t)?"."+t:`[${t}]`} = ${a(e,R)};`)}else p.push(` const result = { result: ${a(e,R)} };`),f=!0;m===R.subKernels.length&&p.push(" return result;")}else e?p.push(` return ${a(e,R)};`):p.push(" return null;")},onUnrecognizedArgumentLookup:e=>{const t=u(e,R.kernelArguments,[],d,c);if(t)return t;const n=u(e,R.kernelConstants,T?Object.keys(T).map(e=>T[e]):[],d,c);return n||null}});let f=!1,m=0;const{source:g,canvas:y,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:E,functions:I,nativeFunctions:_,subKernels:k,immutable:L,argumentTypes:F,constantTypes:D,kernelArguments:$,kernelConstants:C,tactic:M}=i,R=new e(g,{canvas:y,context:d,checkContext:!1,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:E,functions:I,nativeFunctions:_,subKernels:k,immutable:L,argumentTypes:F,constantTypes:D,tactic:M});let G=[];if(d.setIndent(2),R.build.apply(R,t),G.push(d.toString()),d.reset(),R.kernelArguments.forEach((e,n)=>{switch(e.type){case"Integer":case"Boolean":case"Number":case"Float":case"Array":case"Array(2)":case"Array(3)":case"Array(4)":case"HTMLCanvas":case"HTMLImage":case"HTMLVideo":case"Input":d.insertVariable(`uploadValue_${e.name}`,e.uploadValue);break;case"HTMLImageArray":for(let r=0;re.varName).join(", ")}) {`),d.setIndent(4),R.run.apply(R,t),R.renderKernels?R.renderKernels():R.renderOutput&&R.renderOutput(),G.push(" /** start setup uploads for kernel values **/"),R.kernelArguments.forEach(e=>{G.push(" "+e.getStringValueHandler().split("\n").join("\n "))}),G.push(" /** end setup uploads for kernel values **/"),G.push(d.toString()),R.renderOutput===R.renderTexture)if(d.reset(),R.renderKernels){const e=R.renderKernels(),t=d.getContextVariableName(R.texture.texture);G.push(` return {\n result: {\n texture: ${t},\n type: '${e.result.type}',\n toArray: ${o(e.result,t)}\n },`);const{subKernels:n,mappedTextures:r}=R;for(let t=0;t"utils"===e?`const ${t} = ${r[t].toString()};`:null,thisLookup:t=>{if("context"===t)return null;if(e.hasOwnProperty(t))return JSON.stringify(e[t]);throw new Error(`unhandled thisLookup ${t}`)}})}(R)),G.push(" innerKernel.getPixels = getPixels;")),G.push(" return innerKernel;");let N=[];return C.forEach(e=>{N.push(`${e.getStringValueHandler()}`)}),`function kernel(settings) {\n const { context, constants } = settings;\n ${N.join("")}\n ${l||""}\n${G.join("\n")}\n}`}}}),B=e((e,t)=>{t.exports={KernelValue:class{constructor(e,t){const{name:n,kernel:r,context:s,checkContext:i,onRequestContextHandle:a,onUpdateValueMismatch:o,origin:u,strictIntegers:l,type:h,tactic:c}=t;if(!n)throw new Error("name not set");if(!h)throw new Error("type not set");if(!u)throw new Error("origin not set");if("user"!==u&&"constants"!==u)throw new Error(`origin must be "user" or "constants" value is "${u}"`);if(!a)throw new Error("onRequestContextHandle is not set");this.name=n,this.origin=u,this.tactic=c,this.varName="constants"===u?`constants.${n}`:n,this.kernel=r,this.strictIntegers=l,this.type=e.type||h,this.size=e.size||null,this.index=null,this.context=s,this.checkContext=null==i||i,this.contextHandle=null,this.onRequestContextHandle=a,this.onUpdateValueMismatch=o,this.forceUploadEachRun=null}get id(){return`${this.origin}_${name}`}getSource(){throw new Error(`"getSource" not defined on ${this.constructor.name}`)}updateValue(e){throw new Error(`"updateValue" not defined on ${this.constructor.name}`)}}}}),U=e((e,t)=>{const{utils:n}=i(),{KernelValue:r}=B();t.exports={WebGLKernelValue:class extends r{constructor(e,t){super(e,t),this.dimensionsId=null,this.sizeId=null,this.initialValueConstructor=e.constructor,this.onRequestTexture=t.onRequestTexture,this.onRequestIndex=t.onRequestIndex,this.uploadValue=null,this.textureSize=null,this.bitRatio=null,this.prevArg=null}get id(){return`${this.origin}_${n.sanitizeName(this.name)}`}setup(){}rebind(){}getTransferArrayType(e){if(Array.isArray(e[0]))return this.getTransferArrayType(e[0]);switch(e.constructor){case Array:case Int32Array:case Int16Array:case Int8Array:return Float32Array;case Uint8ClampedArray:case Uint8Array:case Uint16Array:case Uint32Array:case Float32Array:case Float64Array:return e.constructor}return console.warn("Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros"),e.constructor}getStringValueHandler(){throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`)}getVariablePrecisionString(){return this.kernel.getVariablePrecisionString(this.textureSize||void 0,this.tactic||void 0)}destroy(){}}}}),K=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueBoolean:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const bool ${this.id} = ${e};\n`:`uniform bool ${this.id};\n`}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),P=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueFloat:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?Number.isInteger(e)?`const float ${this.id} = ${n.glslFloatLiteral(e)};\n`:`const float ${this.id} = ${e};\n`:`uniform float ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1f(this.id,this.uploadValue=e)}}}}),W=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueInteger:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?`const int ${this.id} = ${parseInt(e)};\n`:`uniform int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),j=e((e,t)=>{const{WebGLKernelValue:n}=U(),{Input:s}=r();t.exports={WebGLKernelArray:class extends n{rebind(){if(!this.texture||void 0===this.contextHandle||null===this.contextHandle)return;const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D,this.texture)}checkSize(e,t){if(!this.kernel.validate)return;const{maxTextureSize:n}=this.kernel.constructor.features;if(e>n||t>n)throw e>t?new Error(`Argument texture width of ${e} larger than maximum size of ${n} for your GPU`):e{const{utils:n}=i(),{WebGLKernelArray:r}=j();function s(e){return{width:e.width>0?e.width:e.videoWidth,height:e.height>0?e.height:e.videoHeight}}t.exports={WebGLKernelValueHTMLImage:class extends r{constructor(e,t){super(e,t);const{width:n,height:r}=s(e);this.checkSize(n,r),this.dimensions=[n,r,1],this.textureSize=[n,r],this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue=e),this.kernel.setUniform1i(this.id,this.index)}},mediaSize:s}}),X=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueHTMLImage:r,mediaSize:s}=q();t.exports={WebGLKernelValueDynamicHTMLImage:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:n}=s(e);this.checkSize(t,n),this.dimensions=[t,n,1],this.textureSize=[t,n],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),H=e((e,t)=>{const{WebGLKernelValueHTMLImage:n}=q();t.exports={WebGLKernelValueHTMLVideo:class extends n{}}}),Y=e((e,t)=>{const{WebGLKernelValueDynamicHTMLImage:n}=X();t.exports={WebGLKernelValueDynamicHTMLVideo:class extends n{}}}),Z=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleInput:class extends r{constructor(e,t){super(e,t),this.bitRatio=4;let[r,s,i]=e.size;this.dimensions=new Int32Array([r||1,s||1,i||1]),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return n.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}.value, uploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),J=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleInput:r}=Z();t.exports={WebGLKernelValueDynamicSingleInput:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,s]=e.size;this.dimensions=new Int32Array([t||1,r||1,s||1]),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Q=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueUnsignedInput:class extends r{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e);const[r,s,i]=e.size;this.dimensions=new Int32Array([r||1,s||1,i||1]),this.textureSize=n.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e.value),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return n.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}.value, preUploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(value.constructor);const{context:t}=this;n.flattenTo(e.value,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ee=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueUnsignedInput:r}=Q();t.exports={WebGLKernelValueDynamicUnsignedInput:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,s]=e.size;this.dimensions=new Int32Array([t||1,r||1,s||1]),this.textureSize=n.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const i=this.getTransferArrayType(e.value);this.preUploadValue=new i(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),te=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j(),s="Source and destination textures are the same. Use immutable = true and manually cleanup kernel output texture memory with texture.delete()";t.exports={WebGLKernelValueMemoryOptimizedNumberTexture:class extends r{constructor(e,t){super(e,t);const[n,r]=e.size;this.checkSize(n,r),this.dimensions=e.dimensions,this.textureSize=e.size,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:n}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(s);if(t.mappedTextures){const{mappedTextures:n}=t;for(let t=0;t{const{utils:n}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:r}=te();t.exports={WebGLKernelValueDynamicMemoryOptimizedNumberTexture:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),re=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j(),{sameError:s}=te();t.exports={WebGLKernelValueNumberTexture:class extends r{constructor(e,t){super(e,t);const[n,r]=e.size;this.checkSize(n,r);const{size:s,dimensions:i}=e;this.bitRatio=this.getBitRatio(e),this.dimensions=i,this.textureSize=s,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:n}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(s);if(t.mappedTextures){const{mappedTextures:n}=t;for(let t=0;t{const{utils:n}=i(),{WebGLKernelValueNumberTexture:r}=re();t.exports={WebGLKernelValueDynamicNumberTexture:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ie=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.dimensions=n.getDimensions(e,!0),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return n.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!n.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ae=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray:r}=ie();t.exports={WebGLKernelValueDynamicSingleArray:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=n.getDimensions(e,!0),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),oe=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray1DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=n.getDimensions(e,!0);this.textureSize=n.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],1,1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return n.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flatten2dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ue=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray1DI:r}=oe();t.exports={WebGLKernelValueDynamicSingleArray1DI:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),le=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray2DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=n.getDimensions(e,!0);this.textureSize=n.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return n.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flatten3dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),he=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray2DI:r}=le();t.exports={WebGLKernelValueDynamicSingleArray2DI:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ce=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray3DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=n.getDimensions(e,!0);this.textureSize=n.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],t[3]]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return n.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flatten4dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),pe=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray3DI:r}=ce();t.exports={WebGLKernelValueDynamicSingleArray3DI:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),de=e((e,t)=>{const{WebGLKernelValue:n}=U();t.exports={WebGLKernelValueArray2:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec2 ${this.id} = vec2(${e[0]},${e[1]});\n`:`uniform vec2 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform2fv(this.id,this.uploadValue=e)}}}}),fe=e((e,t)=>{const{WebGLKernelValue:n}=U();t.exports={WebGLKernelValueArray3:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec3 ${this.id} = vec3(${e[0]},${e[1]},${e[2]});\n`:`uniform vec3 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform3fv(this.id,this.uploadValue=e)}}}}),me=e((e,t)=>{const{WebGLKernelValue:n}=U();t.exports={WebGLKernelValueArray4:class extends n{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec4 ${this.id} = vec4(${e[0]},${e[1]},${e[2]},${e[3]});\n`:`uniform vec4 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform4fv(this.id,this.uploadValue=e)}}}}),ge=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueUnsignedArray:class extends r{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e),this.dimensions=n.getDimensions(e,!0),this.textureSize=n.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return n.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}, preUploadValue_${this.name})`])}getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!n.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ye=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueUnsignedArray:r}=ge();t.exports={WebGLKernelValueDynamicUnsignedArray:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=n.getDimensions(e,!0),this.textureSize=n.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const t=this.getTransferArrayType(e);this.preUploadValue=new t(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),xe=e((e,t)=>{const{WebGLKernelValueBoolean:n}=K(),{WebGLKernelValueFloat:r}=P(),{WebGLKernelValueInteger:s}=W(),{WebGLKernelValueHTMLImage:i}=q(),{WebGLKernelValueDynamicHTMLImage:a}=X(),{WebGLKernelValueHTMLVideo:o}=H(),{WebGLKernelValueDynamicHTMLVideo:u}=Y(),{WebGLKernelValueSingleInput:l}=Z(),{WebGLKernelValueDynamicSingleInput:h}=J(),{WebGLKernelValueUnsignedInput:c}=Q(),{WebGLKernelValueDynamicUnsignedInput:p}=ee(),{WebGLKernelValueMemoryOptimizedNumberTexture:d}=te(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:f}=ne(),{WebGLKernelValueNumberTexture:m}=re(),{WebGLKernelValueDynamicNumberTexture:g}=se(),{WebGLKernelValueSingleArray:y}=ie(),{WebGLKernelValueDynamicSingleArray:x}=ae(),{WebGLKernelValueSingleArray1DI:b}=oe(),{WebGLKernelValueDynamicSingleArray1DI:v}=ue(),{WebGLKernelValueSingleArray2DI:S}=le(),{WebGLKernelValueDynamicSingleArray2DI:T}=he(),{WebGLKernelValueSingleArray3DI:A}=ce(),{WebGLKernelValueDynamicSingleArray3DI:w}=pe(),{WebGLKernelValueArray2:E}=de(),{WebGLKernelValueArray3:I}=fe(),{WebGLKernelValueArray4:_}=me(),{WebGLKernelValueUnsignedArray:k}=ge(),{WebGLKernelValueDynamicUnsignedArray:L}=ye(),F={unsigned:{dynamic:{Boolean:n,Integer:s,Float:r,Array:L,"Array(2)":E,"Array(3)":I,"Array(4)":_,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:p,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:n,Float:r,Integer:s,Array:k,"Array(2)":E,"Array(3)":I,"Array(4)":_,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:c,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}},single:{dynamic:{Boolean:n,Integer:s,Float:r,Array:x,"Array(2)":E,"Array(3)":I,"Array(4)":_,"Array1D(2)":v,"Array1D(3)":v,"Array1D(4)":v,"Array2D(2)":T,"Array2D(3)":T,"Array2D(4)":T,"Array3D(2)":w,"Array3D(3)":w,"Array3D(4)":w,Input:h,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:n,Float:r,Integer:s,Array:y,"Array(2)":E,"Array(3)":I,"Array(4)":_,"Array1D(2)":b,"Array1D(3)":b,"Array1D(4)":b,"Array2D(2)":S,"Array2D(3)":S,"Array2D(4)":S,"Array3D(2)":A,"Array3D(3)":A,"Array3D(4)":A,Input:l,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}}};t.exports={lookupKernelValueType:function(e,t,n,r){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!n)throw new Error("precision missing");r.type&&(e=r.type);const s=F[n][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===s[e])return null;if(void 0===s[e])throw new Error(`Could not find a KernelValue for ${e}`);return s[e]},kernelValueMaps:F}}),be=e((e,t)=>{const{GLKernel:n}=M(),{FunctionBuilder:r}=u(),{WebGLFunctionNode:s}=R(),{utils:a}=i(),o=G(),{fragmentShader:l}=N(),{vertexShader:h}=O(),{glKernelString:c}=V(),{lookupKernelValueType:p}=xe();let d=null,f=null,m=null,g=null,y=null;const x=[o],b=[],v={};t.exports={WebGLKernel:class extends n{static get isSupported(){return null!==d||(this.setupFeatureChecks(),d=this.isContextMatch(m)),d}static setupFeatureChecks(){"undefined"!=typeof document?f=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(f=new OffscreenCanvas(0,0)),f&&(m=f.getContext("webgl"),m||f instanceof OffscreenCanvas||(m=f.getContext("experimental-webgl")),m&&m.getExtension&&(g={OES_texture_float:m.getExtension("OES_texture_float"),OES_texture_float_linear:m.getExtension("OES_texture_float_linear"),OES_element_index_uint:m.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:m.getExtension("WEBGL_draw_buffers")},y=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGLRenderingContext&&e instanceof WebGLRenderingContext}static getIsTextureFloat(){return Boolean(g.OES_texture_float)}static getIsDrawBuffers(){return Boolean(g.WEBGL_draw_buffers)}static getChannelCount(){return g.WEBGL_draw_buffers?m.getParameter(g.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return m.getParameter(m.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,n,r){return p(e,t,n,r)}static get testCanvas(){return f}static get testContext(){return m}static get features(){return y}static get fragmentShader(){return l}static get vertexShader(){return h}constructor(e,t){super(e,t),this.program=null,this.pipeline=t.pipeline,this.endianness=a.systemEndianness(),this.extensions={},this.argumentTextureCount=0,this.constantTextureCount=0,this.fragShader=null,this.vertShader=null,this.drawBuffersMap=null,this.maxTexSize=null,this.onRequestSwitchKernel=null,this.texture=null,this.mappedTextures=null,this.mergeSettings(e.settings||t),this.threadDim=null,this.framebuffer=null,this.buffer=null,this.textureCache=[],this.programUniformLocationCache={},this.uniform1fCache={},this.uniform1iCache={},this.uniform2fCache={},this.uniform2fvCache={},this.uniform2ivCache={},this.uniform3fvCache={},this.uniform3ivCache={},this.uniform4fvCache={},this.uniform4ivCache={}}initCanvas(){if("undefined"!=typeof document){const e=document.createElement("canvas");return e.width=2,e.height=2,e}if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(0,0)}initContext(){const e={alpha:!1,depth:!1,antialias:!1};return this.canvas.getContext("webgl",e)||this.canvas.getContext("experimental-webgl",e)}pluginMatchSource(){if("string"!=typeof this.source)return null;if(!this.functions||this.functions.length<1)return this.source;const e=[this.source];for(let t=0;te===r.name)&&t.push(r)}return t}initExtensions(){this.extensions={OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:this.context.getExtension("WEBGL_color_buffer_float")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if(!0===this.optimizeFloatMemory&&!t.isTextureFloat)throw new Error("Float textures are not supported");if("single"===this.precision&&!t.isFloatRead)throw new Error("Single precision not supported");if(this.graphical||null!==this.precision||(this.precision=t.isTextureFloat&&t.isFloatRead?"single":"unsigned"),this.subKernels&&this.subKernels.length>0&&!this.extensions.WEBGL_draw_buffers)throw new Error("could not instantiate draw buffers extension");if(null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"precision"===this.precision&&(this.precision="unsigned",console.warn("Cannot use graphical mode and single precision at the same time")),void(this.texSize=a.clone(this.output))}null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}updateMaxTexSize(){const{texSize:e,canvas:t}=this;if(null===this.maxTexSize){let n=b.indexOf(t);-1===n&&(n=b.length,b.push(t),v[n]=[e[0],e[1]]),this.maxTexSize=v[n]}this.maxTexSize[0]this.argumentNames.length)throw new Error("too many arguments for kernel");const{context:n}=this;let r=0;const s=()=>this.createTexture(),i=()=>this.constantTextureCount+r++,o=e=>{this.switchKernels({type:"argumentMismatch",needed:e})},u=()=>n.TEXTURE0+this.constantTextureCount+this.argumentTextureCount++;for(let r=0;rthis.createTexture(),onRequestIndex:()=>r++,onRequestContextHandle:()=>t.TEXTURE0+this.constantTextureCount++});this.constantBitRatios[s]=l.bitRatio,this.kernelConstants.push(l),l.setup(),l.forceUploadEachRun&&this.forceUploadKernelConstants.push(l)}}build(){if(this.built)return;if(this.initExtensions(),this.validateSettings(arguments),this.setupConstants(arguments),this.fallbackRequested)return;if(this.setupArguments(arguments),this.fallbackRequested)return;this.updateMaxTexSize(),this.buildWithOptimizer(()=>this.translateSource());const e=this.pickRenderStrategy(arguments);if(e)return e;const{texSize:t,context:n,canvas:r}=this;n.enable(n.SCISSOR_TEST),this.pipeline&&this.precision,n.viewport(0,0,this.maxTexSize[0],this.maxTexSize[1]),r.width=this.maxTexSize[0],r.height=this.maxTexSize[1];const s=this.threadDim=Array.from(this.output);for(;s.length<3;)s.push(1);const i=this.getVertexShader(arguments),a=n.createShader(n.VERTEX_SHADER);n.shaderSource(a,i),n.compileShader(a),this.vertShader=a;const o=this.getFragmentShader(arguments),u=n.createShader(n.FRAGMENT_SHADER);if(n.shaderSource(u,o),n.compileShader(u),this.fragShader=u,this.debug&&(console.log("GLSL Shader Output:"),console.log(o)),!n.getShaderParameter(a,n.COMPILE_STATUS))throw new Error("Error compiling vertex shader: "+n.getShaderInfoLog(a));if(!n.getShaderParameter(u,n.COMPILE_STATUS))throw new Error("Error compiling fragment shader: "+n.getShaderInfoLog(u));const l=this.program=n.createProgram();n.attachShader(l,a),n.attachShader(l,u),n.linkProgram(l),this.framebuffer=n.createFramebuffer(),this.framebuffer.width=t[0],this.framebuffer.height=t[1],this.rawValueFramebuffers={};const h=new Float32Array([-1,-1,1,-1,-1,1,1,1]),c=new Float32Array([0,0,1,0,0,1,1,1]),p=h.byteLength;let d=this.buffer;d?n.bindBuffer(n.ARRAY_BUFFER,d):(d=this.buffer=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,d),n.bufferData(n.ARRAY_BUFFER,h.byteLength+c.byteLength,n.STATIC_DRAW)),n.bufferSubData(n.ARRAY_BUFFER,0,h),n.bufferSubData(n.ARRAY_BUFFER,p,c);const f=n.getAttribLocation(this.program,"aPos");-1!==f&&(n.enableVertexAttribArray(f),n.vertexAttribPointer(f,2,n.FLOAT,!1,0,0));const m=n.getAttribLocation(this.program,"aTexCoord");-1!==m&&(n.enableVertexAttribArray(m),n.vertexAttribPointer(m,2,n.FLOAT,!1,0,p)),n.bindFramebuffer(n.FRAMEBUFFER,this.framebuffer);let g=0;n.useProgram(this.program);for(let e in this.constants)this.kernelConstants[g++].updateValue(this.constants[e]);this._setupOutputTexture(),null!==this.subKernels&&this.subKernels.length>0&&(this._mappedTextureSwitched={},this._setupSubOutputTextures()),this.buildSignature(arguments),this.built=!0}translateSource(){const e=r.fromKernel(this,s,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}setupReturnTypes(e){if(this.graphical||this.returnType||(this.returnType=e.getKernelResultType()),this.subKernels&&this.subKernels.length>0)for(let t=0;tt.source&&e.match(t.functionMatch)?t.source:"").join("\n")}_getConstantsString(){const e=[],{threadDim:t,texSize:n}=this;return this.dynamicOutput?e.push("uniform ivec3 uOutputDim","uniform ivec2 uTexSize"):e.push(`ivec3 uOutputDim = ivec3(${t[0]}, ${t[1]}, ${t[2]})`,`ivec2 uTexSize = ivec2(${n[0]}, ${n[1]})`),a.linesToString(e)}_getTextureCoordinate(){const e=this.subKernels;return null===e||e.length<1?"varying vec2 vTexCoord;\n":"out vec2 vTexCoord;\n"}_getDecode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getEncode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getDivideWithIntegerCheckString(){return this.fixIntegerDivisionAccuracy?"float divWithIntCheck(float x, float y) {\n if (floor(x) == x && floor(y) == y) {\n float q = floor(x / y + 0.5);\n if (y * q == x) {\n return q;\n }\n }\n return x / y;\n}\n\nfloat integerCorrectionModulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -(number - (divisor * floor(divWithIntCheck(number, divisor))));\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return number - (divisor * floor(divWithIntCheck(number, divisor)));\n}":""}_getMainArgumentsString(e){const t=[],{argumentNames:n}=this;for(let r=0;r{if(t.hasOwnProperty(n))return t[n];throw`unhandled artifact ${n}`})}getFragmentShader(e){return null!==this.compiledFragmentShader?this.compiledFragmentShader:this.compiledFragmentShader=this.replaceArtifacts(this.constructor.fragmentShader,this._getFragShaderArtifactMap(e))}getVertexShader(e){return null!==this.compiledVertexShader?this.compiledVertexShader:this.compiledVertexShader=this.replaceArtifacts(this.constructor.vertexShader,this._getVertShaderArtifactMap(e))}toString(){const e=a.linesToString(["const gl = context"]);return c(this.constructor,arguments,this,e)}destroy(e){if(!this.context)return;this.buffer&&this.context.deleteBuffer(this.buffer),this.framebuffer&&this.context.deleteFramebuffer(this.framebuffer);for(const e in this.rawValueFramebuffers){for(const t in this.rawValueFramebuffers[e])this.context.deleteFramebuffer(this.rawValueFramebuffers[e][t]),delete this.rawValueFramebuffers[e][t];delete this.rawValueFramebuffers[e]}if(this.vertShader&&this.context.deleteShader(this.vertShader),this.fragShader&&this.context.deleteShader(this.fragShader),this.program&&this.context.deleteProgram(this.program),this.texture){this.texture.delete();const e=this.textureCache.indexOf(this.texture.texture);e>-1&&this.textureCache.splice(e,1),this.texture=null}if(this.mappedTextures&&this.mappedTextures.length){for(let e=0;e-1&&this.textureCache.splice(n,1)}this.mappedTextures=null}if(this.kernelArguments)for(let e=0;e0;){const e=this.textureCache.pop();this.context.deleteTexture(e)}if(e){const e=b.indexOf(this.canvas);e>=0&&(b[e]=null,v[e]=null)}if(this.destroyExtensions(),delete this.context,delete this.canvas,!this.gpu)return;const t=this.gpu.kernels.indexOf(this);-1!==t&&this.gpu.kernels.splice(t,1)}destroyExtensions(){this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("WEBGL_lose_context");t&&t.loseContext()}toJSON(){const e=super.toJSON();return e.functionNodes=r.fromKernel(this,s).toJSON(),e.settings.threadDim=this.threadDim,e}}}}),ve=e((e,t)=>{const r=n(),{WebGLKernel:s}=be(),{glKernelString:i}=V();let a=null,o=null,u=null,l=null,h=null;t.exports={HeadlessGLKernel:class extends s{static get isSupported(){return null!==a||(this.setupFeatureChecks(),a=null!==u),a}static setupFeatureChecks(){if(o=null,l=null,"function"==typeof r)try{if(u=r(2,2,{preserveDrawingBuffer:!0}),!u||!u.getExtension)return;l={STACKGL_resize_drawingbuffer:u.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:u.getExtension("STACKGL_destroy_context"),OES_texture_float:u.getExtension("OES_texture_float"),OES_texture_float_linear:u.getExtension("OES_texture_float_linear"),OES_element_index_uint:u.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:u.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:u.getExtension("WEBGL_color_buffer_float")},h=this.getFeatures()}catch(e){console.warn(e)}}static isContextMatch(e){try{return"ANGLE"===e.getParameter(e.RENDERER)}catch(e){return!1}}static getIsTextureFloat(){return Boolean(l.OES_texture_float)}static getIsDrawBuffers(){return Boolean(l.WEBGL_draw_buffers)}static getChannelCount(){return l.WEBGL_draw_buffers?u.getParameter(l.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return u.getParameter(u.MAX_TEXTURE_SIZE)}static get testCanvas(){return o}static get testContext(){return u}static get features(){return h}initCanvas(){return{}}initContext(){return r(2,2,{preserveDrawingBuffer:!0})}initExtensions(){this.extensions={STACKGL_resize_drawingbuffer:this.context.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:this.context.getExtension("STACKGL_destroy_context"),OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers")}}build(){super.build.apply(this,arguments),this.fallbackRequested||this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1])}destroyExtensions(){this.extensions.STACKGL_resize_drawingbuffer=null,this.extensions.STACKGL_destroy_context=null,this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("STACKGL_destroy_context");t&&t.destroy&&t.destroy()}toString(){return i(this.constructor,arguments,this,"const gl = context || require('gl')(1, 1);\n"," if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n")}setOutput(e){return super.setOutput(e),this.graphical&&this.extensions.STACKGL_resize_drawingbuffer&&this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1]),this}}}}),Se=e((e,t)=>{const{utils:n}=i(),{WebGLFunctionNode:r}=R();t.exports={WebGL2FunctionNode:class extends r{astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),s=n.sanitizeName(e.name);if("Infinity"===e.name)t.push("intBitsToFloat(2139095039)");else if("Boolean"===r)if(this.argumentNames.indexOf(s)>-1){const n=this.markupUserName(e.name);t.push(n.startsWith("cellShadow_")?n:`bool(${n})`)}else t.push(`user_${s}`);else t.push(this.markupUserName(e.name));return t}}}}),Te=e((e,t)=>{t.exports={fragmentShader:`#version 300 es\n__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n__SAMPLER_2D_ARRAY_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nin vec2 vTexCoord;\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x/y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n return texel[channel] * 255.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n index = index / 4;\n vec4 texel = texture(tex, st / vec2(texSize));\n return texel[channel];\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, st / vec2(texSize));\n}\n\nvec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, vec3(st / vec2(texSize), z));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n\n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),Ae=e((e,t)=>{t.exports={vertexShader:"#version 300 es\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nin vec2 aPos;\nin vec2 aTexCoord;\n\nout vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),we=e((e,t)=>{const{WebGLKernelValueBoolean:n}=K();t.exports={WebGL2KernelValueBoolean:class extends n{}}}),Ee=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueFloat:r}=P();t.exports={WebGL2KernelValueFloat:class extends r{}}}),Ie=e((e,t)=>{const{WebGLKernelValueInteger:n}=W();t.exports={WebGL2KernelValueInteger:class extends n{getSource(e){const t=this.getVariablePrecisionString();return"constants"===this.origin?`const ${t} int ${this.id} = ${parseInt(e)};\n`:`uniform ${t} int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),_e=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueHTMLImage:r}=q();t.exports={WebGL2KernelValueHTMLImage:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),ke=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueDynamicHTMLImage:r}=X();t.exports={WebGL2KernelValueDynamicHTMLImage:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Le=e((e,t)=>{const{utils:n}=i(),{WebGLKernelArray:r}=j();t.exports={WebGL2KernelValueHTMLImageArray:class extends r{constructor(e,t){super(e,t),this.checkSize(e[0].width,e[0].height),this.dimensions=[e[0].width,e[0].height,e.length],this.textureSize=[e[0].width,e[0].height]}defineTexture(){const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D_ARRAY,this.texture),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MIN_FILTER,e.NEAREST)}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D_ARRAY,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage3D(t.TEXTURE_2D_ARRAY,0,t.RGBA,e[0].width,e[0].height,e.length,0,t.RGBA,t.UNSIGNED_BYTE,null);for(let n=0;n{const{utils:n}=i(),{WebGL2KernelValueHTMLImageArray:r}=Le();t.exports={WebGL2KernelValueDynamicHTMLImageArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:n}=e[0];this.checkSize(t,n),this.dimensions=[t,n,e.length],this.textureSize=[t,n],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),De=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueHTMLImage:r}=_e();t.exports={WebGL2KernelValueHTMLVideo:class extends r{}}}),$e=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueDynamicHTMLImage:r}=ke();t.exports={WebGL2KernelValueDynamicHTMLVideo:class extends r{}}}),Ce=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleInput:r}=Z();t.exports={WebGL2KernelValueSingleInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;n.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Me=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueSingleInput:r}=Ce();t.exports={WebGL2KernelValueDynamicSingleInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,s]=e.size;this.dimensions=new Int32Array([t||1,r||1,s||1]),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Re=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueUnsignedInput:r}=Q();t.exports={WebGL2KernelValueUnsignedInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Ge=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueDynamicUnsignedInput:r}=ee();t.exports={WebGL2KernelValueDynamicUnsignedInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Ne=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:r}=te();t.exports={WebGL2KernelValueMemoryOptimizedNumberTexture:class extends r{getSource(){const{id:e,sizeId:t,textureSize:r,dimensionsId:s,dimensions:i}=this,a=this.getVariablePrecisionString();return n.linesToString([`uniform sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${r[0]}, ${r[1]})`,`${a} ivec3 ${s} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Oe=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:r}=ne();t.exports={WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:class extends r{getSource(){return n.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}}}}),ze=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueNumberTexture:r}=re();t.exports={WebGL2KernelValueNumberTexture:class extends r{getSource(){const{id:e,sizeId:t,textureSize:r,dimensionsId:s,dimensions:i}=this,a=this.getVariablePrecisionString();return n.linesToString([`uniform ${a} sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${r[0]}, ${r[1]})`,`${a} ivec3 ${s} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Ve=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueDynamicNumberTexture:r}=se();t.exports={WebGL2KernelValueDynamicNumberTexture:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Be=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray:r}=ie();t.exports={WebGL2KernelValueSingleArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!n.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Ue=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueSingleArray:r}=Be();t.exports={WebGL2KernelValueDynamicSingleArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=n.getDimensions(e,!0),this.textureSize=n.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ke=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray1DI:r}=oe();t.exports={WebGL2KernelValueSingleArray1DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Pe=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueSingleArray1DI:r}=Ke();t.exports={WebGL2KernelValueDynamicSingleArray1DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),We=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray2DI:r}=le();t.exports={WebGL2KernelValueSingleArray2DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),je=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueSingleArray2DI:r}=We();t.exports={WebGL2KernelValueDynamicSingleArray2DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),qe=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueSingleArray3DI:r}=ce();t.exports={WebGL2KernelValueSingleArray3DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;n.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Xe=e((e,t)=>{const{utils:n}=i(),{WebGL2KernelValueSingleArray3DI:r}=qe();t.exports={WebGL2KernelValueDynamicSingleArray3DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),He=e((e,t)=>{const{WebGLKernelValueArray2:n}=de();t.exports={WebGL2KernelValueArray2:class extends n{}}}),Ye=e((e,t)=>{const{WebGLKernelValueArray3:n}=fe();t.exports={WebGL2KernelValueArray3:class extends n{}}}),Ze=e((e,t)=>{const{WebGLKernelValueArray4:n}=me();t.exports={WebGL2KernelValueArray4:class extends n{}}}),Je=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueUnsignedArray:r}=ge();t.exports={WebGL2KernelValueUnsignedArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Qe=e((e,t)=>{const{utils:n}=i(),{WebGLKernelValueDynamicUnsignedArray:r}=ye();t.exports={WebGL2KernelValueDynamicUnsignedArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return n.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),et=e((e,t)=>{const{WebGL2KernelValueBoolean:n}=we(),{WebGL2KernelValueFloat:r}=Ee(),{WebGL2KernelValueInteger:s}=Ie(),{WebGL2KernelValueHTMLImage:i}=_e(),{WebGL2KernelValueDynamicHTMLImage:a}=ke(),{WebGL2KernelValueHTMLImageArray:o}=Le(),{WebGL2KernelValueDynamicHTMLImageArray:u}=Fe(),{WebGL2KernelValueHTMLVideo:l}=De(),{WebGL2KernelValueDynamicHTMLVideo:h}=$e(),{WebGL2KernelValueSingleInput:c}=Ce(),{WebGL2KernelValueDynamicSingleInput:p}=Me(),{WebGL2KernelValueUnsignedInput:d}=Re(),{WebGL2KernelValueDynamicUnsignedInput:f}=Ge(),{WebGL2KernelValueMemoryOptimizedNumberTexture:m}=Ne(),{WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:g}=Oe(),{WebGL2KernelValueNumberTexture:y}=ze(),{WebGL2KernelValueDynamicNumberTexture:x}=Ve(),{WebGL2KernelValueSingleArray:b}=Be(),{WebGL2KernelValueDynamicSingleArray:v}=Ue(),{WebGL2KernelValueSingleArray1DI:S}=Ke(),{WebGL2KernelValueDynamicSingleArray1DI:T}=Pe(),{WebGL2KernelValueSingleArray2DI:A}=We(),{WebGL2KernelValueDynamicSingleArray2DI:w}=je(),{WebGL2KernelValueSingleArray3DI:E}=qe(),{WebGL2KernelValueDynamicSingleArray3DI:I}=Xe(),{WebGL2KernelValueArray2:_}=He(),{WebGL2KernelValueArray3:k}=Ye(),{WebGL2KernelValueArray4:L}=Ze(),{WebGL2KernelValueUnsignedArray:F}=Je(),{WebGL2KernelValueDynamicUnsignedArray:D}=Qe(),$={unsigned:{dynamic:{Boolean:n,Integer:s,Float:r,Array:D,"Array(2)":_,"Array(3)":k,"Array(4)":L,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:f,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:n,Float:r,Integer:s,Array:F,"Array(2)":_,"Array(3)":k,"Array(4)":L,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:d,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:g,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}},single:{dynamic:{Boolean:n,Integer:s,Float:r,Array:v,"Array(2)":_,"Array(3)":k,"Array(4)":L,"Array1D(2)":T,"Array1D(3)":T,"Array1D(4)":T,"Array2D(2)":w,"Array2D(3)":w,"Array2D(4)":w,"Array3D(2)":I,"Array3D(3)":I,"Array3D(4)":I,Input:p,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:n,Float:r,Integer:s,Array:b,"Array(2)":_,"Array(3)":k,"Array(4)":L,"Array1D(2)":S,"Array1D(3)":S,"Array1D(4)":S,"Array2D(2)":A,"Array2D(3)":A,"Array2D(4)":A,"Array3D(2)":E,"Array3D(3)":E,"Array3D(4)":E,Input:c,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:m,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}}};t.exports={kernelValueMaps:$,lookupKernelValueType:function(e,t,n,r){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!n)throw new Error("precision missing");r.type&&(e=r.type);const s=$[n][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===s[e])return null;if(void 0===s[e])throw new Error(`Could not find a KernelValue for ${e}`);return s[e]}}}),tt=e((e,t)=>{const{WebGLKernel:n}=be(),{WebGL2FunctionNode:r}=Se(),{FunctionBuilder:s}=u(),{utils:a}=i(),{fragmentShader:o}=Te(),{vertexShader:l}=Ae(),{lookupKernelValueType:h}=et();let c=null,p=null,d=null,f=null;t.exports={WebGL2Kernel:class extends n{static get isSupported(){return null!==c||(this.setupFeatureChecks(),c=this.isContextMatch(d)),c}static setupFeatureChecks(){"undefined"!=typeof document?p=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(p=new OffscreenCanvas(0,0)),p&&(d=p.getContext("webgl2"),d&&d.getExtension&&(d.getExtension("EXT_color_buffer_float"),d.getExtension("OES_texture_float_linear"),f=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext}static getFeatures(){const e=this.testContext;return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),kernelMap:!0,isTextureFloat:!0,isDrawBuffers:!0,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static getIsTextureFloat(){return!0}static getChannelCount(){return d.getParameter(d.MAX_DRAW_BUFFERS)}static getMaxTextureSize(){return d.getParameter(d.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,n,r){return h(e,t,n,r)}static get testCanvas(){return p}static get testContext(){return d}static get features(){return f}static get fragmentShader(){return o}static get vertexShader(){return l}initContext(){return this.canvas.getContext("webgl2",{alpha:!1,depth:!1,antialias:!1})}initExtensions(){this.extensions={EXT_color_buffer_float:this.context.getExtension("EXT_color_buffer_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if("single"===this.precision&&!t.isFloatRead)throw new Error("Float texture outputs are not supported");if(this.graphical||null!==this.precision||(this.precision=t.isFloatRead?"single":"unsigned"),null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"single"===this.precision&&(console.warn("Cannot use graphical mode and single precision at the same time"),this.precision="unsigned"),void(this.texSize=a.clone(this.output))}!this.graphical&&null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}translateSource(){const e=s.fromKernel(this,r,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}drawBuffers(){this.context.drawBuffers(this.drawBuffersMap)}getTextureFormat(){const{context:e}=this;switch(this.getInternalFormat()){case e.R32F:return e.RED;case e.RG32F:return e.RG;case e.RGBA32F:case e.RGBA:return e.RGBA;default:throw new Error("Unknown internal format")}}renderValues(){return void 0===this._tightRead&&this._detectTightRead(),super.renderValues()}renderKernelsToArrays(){return void 0===this._tightRead&&this._detectTightRead(),super.renderKernelsToArrays()}readFloatPixelsToFloat32Array(){if(!this._tightRead)return super.readFloatPixelsToFloat32Array();const{texSize:e,context:t}=this,n=e[0],r=e[1],s=new Float32Array(n*r);return t.readPixels(0,0,n,r,t.RED,t.FLOAT,s),s}renderOutputAsync(){return this.renderOutput!==this.renderValues?Promise.resolve(this.renderOutput()):this.renderValuesAsync()}renderValuesAsync(){void 0===this._tightRead&&this._detectTightRead();const e=this.formatValues,[t,n,r]=this.output;return this.transferValuesAsync().then(s=>e(s,t,n,r))}transferValuesAsync(){const{texSize:e,context:t}=this,n=e[0],r=e[1];let s,i,a;"single"===this.precision?(s=this._tightRead?t.RED:t.RGBA,i=t.FLOAT,a=new Float32Array(n*r*(this._tightRead?1:4))):(s=t.RGBA,i=t.UNSIGNED_BYTE,a=new Uint8Array(n*r*4));const o=t.createBuffer();t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.bufferData(t.PIXEL_PACK_BUFFER,a.byteLength,t.STREAM_READ),t.readPixels(0,0,n,r,s,i,0),t.bindBuffer(t.PIXEL_PACK_BUFFER,null);const u=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);return t.flush(),this._pollFence(u).then(()=>(t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.getBufferSubData(t.PIXEL_PACK_BUFFER,0,a),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),t.deleteBuffer(o),"single"===this.precision?a:new Float32Array(a.buffer)),e=>{throw t.deleteBuffer(o),e})}_pollFence(e){const t=this.context;return new Promise((n,r)=>{let s,i=null;"undefined"!=typeof MessageChannel?(i=new MessageChannel,i.port1.onmessage=()=>o(),s=()=>i.port2.postMessage(0)):s=()=>setTimeout(o,0);const a=(n,r)=>{t.deleteSync(e),i&&(i.port1.close(),i.port2.close()),n(r)},o=()=>{if(t.isContextLost())return a(r,new Error("WebGL context lost while awaiting kernel result"));const i=t.clientWaitSync(e,0,0);return i===t.ALREADY_SIGNALED||i===t.CONDITION_SATISFIED?a(n):i===t.WAIT_FAILED?a(r,new Error("clientWaitSync failed while awaiting kernel result")):void s()};o()})}_detectTightRead(){const e=this.context;this._tightRead=!1,e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t="Number"===this.returnType||"Float"===this.returnType||"Integer"===this.returnType||"LiteralInteger"===this.returnType;if("single"===this.precision&&!this.optimizeFloatMemory&&!this.graphical&&t&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)===e.RED&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)===e.FLOAT){if(this.formatValues===a.erectFloat)this.formatValues=a.erectMemoryOptimizedFloat;else if(this.formatValues===a.erect2DFloat)this.formatValues=a.erectMemoryOptimized2DFloat;else if(this.formatValues===a.erect3DFloat)this.formatValues=a.erectMemoryOptimized3DFloat;else if(this.formatValues!==a.erectMemoryOptimizedFloat&&this.formatValues!==a.erectMemoryOptimized2DFloat&&this.formatValues!==a.erectMemoryOptimized3DFloat)return;this._tightRead=!0}}getInternalFormat(){const{context:e}=this;if("single"===this.precision)switch(this.returnType){case"Number":case"Float":case"Integer":return this.optimizeFloatMemory?e.RGBA32F:e.R32F;case"Array(2)":return e.RG32F;case"Array(3)":case"Array(4)":return e.RGBA32F;default:throw new Error("Unhandled return type")}return e.RGBA}_setupOutputTexture(){const e=this.context;if(this.texture)return e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0),void(this._tightRead=void 0);e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t=e.createTexture(),n=this.texSize;e.activeTexture(e.TEXTURE0+this.constantTextureCount+this.argumentTextureCount),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);const r=this.getInternalFormat();"single"===this.precision?e.texStorage2D(e.TEXTURE_2D,1,r,n[0],n[1]):e.texImage2D(e.TEXTURE_2D,0,r,n[0],n[1],0,r,e.UNSIGNED_BYTE,null),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),this.texture=new this.TextureConstructor({texture:t,size:n,dimensions:this.threadDim,output:this.output,context:this.context,internalFormat:this.getInternalFormat(),textureFormat:this.getTextureFormat(),kernel:this}),this._tightRead=void 0}_setupSubOutputTextures(){const e=this.context;if(this.mappedTextures){for(let t=0;t{const{utils:n}=i(),{FunctionNode:r}=h();const s={Number:"f32",Float:"f32",Integer:"i32",LiteralInteger:"f32",Boolean:"bool","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4"},a={"===":"==","!==":"!="},o=["x","y","z","w"],u={pow:"_pow",round:"_round"},l={ceil:!0,floor:!0,_round:!0};t.exports={WGSLFunctionNode:class extends r{get requiresSequenceFreeForInit(){return!0}wgslFloat(e){if(e===1/0)return"0x1.fffffep+127";if(e===-1/0)return"-0x1.fffffep+127";if(e>34028234663852886e22)return"0x1.fffffep+127";if(e<-34028234663852886e22)return"-0x1.fffffep+127";const t=`${e}`;return-1!==t.indexOf(".")||-1!==t.indexOf("e")||-1!==t.indexOf("E")?t:`${t}.0`}wgslInt(e){return`${Math.round(e)}`}mangleFunctionName(e){return`fn_${n.sanitizeName(e)}`}getLookupType(e){return"WebGPUBuffer"===e?"Number":super.getLookupType(e)}astUpdateExpression(e,t){return this.astGeneric(e.argument,t),t.push(e.operator),t}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const n=this.getType(e.consequent),r=this.getType(e.alternate);if(null===n&&null===r)return t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t;let s="LiteralInteger"===n?"Number":n;"Integer"!==s||"Number"!==r&&"Float"!==r||(s="Number");const i=e=>{const n=this.getType(e);switch(s){case"Number":case"Float":"Integer"===n?this.castValueToFloat(e,t):"LiteralInteger"===n?this.castLiteralToFloat(e,t):this.astGeneric(e,t);break;case"Integer":"Number"===n||"Float"===n?this.castValueToInteger(e,t):"LiteralInteger"===n?this.castLiteralToInteger(e,t):this.astGeneric(e,t);break;default:this.astGeneric(e,t)}};return t.push("select("),i(e.alternate),t.push(", "),i(e.consequent),t.push(", "),this.astGeneric(e.test,t),t.push(")"),t}astFunction(e,t){if(this.isRootKernel){for(let n=0;n0&&t.push(", ");let a=this.argumentTypes[this.argumentNames.indexOf(i)];if(!a)throw this.astErrorOutput(`Unknown argument ${i} type`,e);"LiteralInteger"===a&&(this.argumentTypes[r]=a="Number");const o=s[a];if(!o)throw this.astErrorOutput(`WebGPU backend does not yet support ${a} arguments to helper functions`,e);t.push(`user_${n.sanitizeName(i)} : ${o}`)}t.push(")"),i&&t.push(` -> ${i}`),t.push(" {\n");for(let n=0;n>":!0,">>>":!0}[e.operator])return null;const n=e=>{switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer")}};return t.push("("),">>>"===e.operator?(t.push("bitcast(bitcast("),n(e.left),t.push(") >> u32("),n(e.right),t.push("))")):"<<"===e.operator||">>"===e.operator?(n(e.left),t.push(` ${e.operator} u32(`),n(e.right),t.push(")")):(n(e.left),t.push(` ${e.operator} `),n(e.right)),t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){if("~"!==e.operator)return null;switch(t.push("~("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)?t:"+"===e.operator?(this.astGeneric(e.argument,t),t):(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t)}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("f32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),s=n.sanitizeName(e.name);return"Infinity"===e.name?(t.push("0x1.fffffep+127"),t):!this.isRootKernel||-1===this.argumentNames.indexOf(e.name)||"Number"!==r&&"Float"!==r&&"Integer"!==r&&"Boolean"!==r?(t.push(`user_${s}`),t):("Boolean"===r?t.push(`bool(params.user_${s})`):t.push(`params.user_${s}`),t)}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const n=[],r=[],s=[],i=[];let a=null;if(e.init){const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,n);for(let e=0;e0&&t.push(n.join(""),"\n"),t.push(`for (var ${e} : i32 = 0;${e}0&&t.push(`if (!(${r.join("")})) { break; }\n`),t.push(i.join("")),t.push(`\n${s.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const n=this.getInternalVariableName("safeI");return t.push(`for (var ${n} : i32 = 0;${n}{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const n in e)if("loc"!==n&&"range"!==n&&"parent"!==n&&t(e[n]))return!0;return!1};if(t(n[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",n[e])}for(let e=0;ee+1){l=!0,this.astSwitchCaseConsequent(r[e].consequent,u);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(r[e].consequent,t),t.push("\n}")}return l&&(t.push(" else {"),t.push(u.join("")),t.push("}")),t.push("\n"),t}astThisExpression(e,t){return t.push("this"),t}astSequenceExpression(e,t){const{expressions:n}=e;if(1===n.length)return this.astGeneric(n[0],t),t;throw this.astErrorOutput("WebGPU backend does not yet support the comma operator",e)}astMemberExpression(e,t){const{property:r,name:i,signature:a,origin:o,type:u,xProperty:l,yProperty:h,zProperty:c}=this.getMemberExpressionDetails(e);switch(a){case"value.thread.value":case"this.thread.value":if("x"!==i&&"y"!==i&&"z"!==i)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`i32(threadGid.${i})`),t;case"this.output.value":{const n={x:0,y:1,z:2}[i];if(void 0===n)throw this.astErrorOutput("Unexpected expression",e);if(this.dynamicOutput){const e=`params.output${i.toUpperCase()}`;this.isState("casting-to-float")?t.push(`f32(${e})`):t.push(`i32(${e})`)}else this.isState("casting-to-integer")?t.push(`${this.output[n]}`):t.push(`${this.output[n]}.0`);return t}case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===o)return t.push(this.wgslFloat(Math[i])),t;switch(r){case"r":return t.push(`user_${n.sanitizeName(i)}.x`),t;case"g":return t.push(`user_${n.sanitizeName(i)}.y`),t;case"b":return t.push(`user_${n.sanitizeName(i)}.z`),t;case"a":return t.push(`user_${n.sanitizeName(i)}.w`),t}break;case"this.constants.value":{const n=this.constants[i];switch(u){case"Integer":return this.isState("casting-to-float")?t.push(this.wgslFloat(n)):t.push(this.wgslInt(n)),t;case"Number":case"Float":return this.isState("casting-to-integer")?t.push(this.wgslInt(n)):t.push(this.wgslFloat(n)),t;case"Boolean":return t.push(n?"true":"false"),t;case"Array(2)":case"Array(3)":case"Array(4)":{const e=parseInt(u.substring(6),10),r=[];for(let t=0;t4)throw this.astErrorOutput("this.color takes (r, g, b) or (r, g, b, a)",e);t.push("kernelColor(data_index");for(let n=0;n0&&t.push(", "),s){case"Integer":this.castValueToFloat(r,t);break;case"LiteralInteger":this.castLiteralToFloat(r,t);break;default:this.astGeneric(r,t)}}else{const s=this.lookupFunctionArgumentTypes(r)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(r,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("i32("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("f32("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.pushState("building-integer"),this.astGeneric(a,t),this.popState("building-integer");continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){"Identifier"===a.type?t.push(`user_${n.sanitizeName(a.name)}`):this.astGeneric(a,t);continue}break;case"Array":case"Array2D":case"Array3D":case"Input":case"WebGPUBuffer":throw this.astErrorOutput("WebGPU backend does not yet support array arguments to helper functions",e)}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),a&&t.push(")"),t}astArrayExpression(e,t){switch(this.getType(e)){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":throw this.astErrorOutput("WebGPU backend does not yet support Matrix types",e)}const n=e.elements.length;t.push(`vec${n}(`);for(let r=0;r0&&t.push(", ");const n=e.elements[r];switch(this.getType(n)){case"Integer":this.castValueToFloat(n,t);break;case"LiteralInteger":this.castLiteralToFloat(n,t);break;default:this.astGeneric(n,t)}}return t.push(")"),t}memberExpressionXYZ(e,t,n,r){return n?r.push(this.memberExpressionPropertyMarkup(n),", "):r.push("0, "),t?r.push(this.memberExpressionPropertyMarkup(t),", "):r.push("0, "),r.push(this.memberExpressionPropertyMarkup(e)),r}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("building-integer");break;default:this.astGeneric(e,t)}return t.join("")}}}}),rt=e((e,t)=>{let n=null;t.exports={WebGPUContext:class e{static get isSupported(){return"undefined"!=typeof navigator&&!!navigator.gpu}static acquire(){if(n)return n;const t=(async()=>{if(!e.isSupported)throw new Error("WebGPU is not supported on this platform (navigator.gpu is missing)");const r=await navigator.gpu.requestAdapter();if(!r)throw new Error("WebGPU is present (navigator.gpu) but no adapter is available. On headless Chromium there is no adapter; run headed. Use `await GPU.isWebGPUAvailable()` to feature-detect.");const s=await r.requestDevice({requiredLimits:{maxStorageBufferBindingSize:r.limits.maxStorageBufferBindingSize,maxBufferSize:r.limits.maxBufferSize}}),i={adapter:r,device:s,isLost:!1};return s.lost.then(e=>{i.isLost=!0,"destroyed"!==e.reason&&console.error(`gpu.js [webgpu]: device lost: ${e.message}`),n===t&&(n=null)}),s.onuncapturederror=e=>{console.error(`gpu.js [webgpu]: ${e.error.message}`)},i})();return t.catch(()=>{n===t&&(n=null)}),n=t}static destroy(){if(!n)return Promise.resolve();const e=n;return n=null,e.then(({device:e})=>{e.destroy()},()=>{})}}}}),st=e((e,t)=>{t.exports={WebGPUBufferResult:class e{constructor(e){this.buffer=e.buffer,this.output=e.output,this.componentCount=e.componentCount||1,this.context=e.context,this.kernel=e.kernel,this.type="WebGPUBuffer",this._deleted=!1,this.buffer._refs?this.buffer._refs++:this.buffer._refs=1}toArray(){return this._deleted?Promise.reject(new Error("WebGPUBufferResult has been deleted")):this.kernel.readBufferResult(this)}delete(){this._deleted||(this._deleted=!0,0===--this.buffer._refs&&this.buffer.destroy())}clone(){return new e(this)}}}}),it=e((e,t)=>{const{Kernel:n}=a(),{FunctionBuilder:s}=u(),{WGSLFunctionNode:o}=nt(),{WebGPUContext:l}=rt(),{WebGPUBufferResult:h}=st(),{utils:c}=i(),{Input:p}=r(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0}),f={_pow:"fn _pow(v1 : f32, v2 : f32) -> f32 {\n if (v2 == 0.0) { return 1.0; }\n return pow(v1, v2);\n}",_round:"fn _round(x : f32) -> f32 {\n return floor(x + 0.5);\n}",cbrt:"fn cbrt(x : f32) -> f32 {\n return sign(x) * pow(abs(x), 1.0 / 3.0);\n}",expm1:"fn expm1(x : f32) -> f32 {\n return exp(x) - 1.0;\n}",fround:"fn fround(x : f32) -> f32 {\n return x;\n}",imul:"fn imul(a : f32, b : f32) -> f32 {\n return f32(i32(a) * i32(b));\n}",log10:`fn log10(x : f32) -> f32 {\n return log2(x) * ${1/Math.log2(10)};\n}`,log1p:"fn log1p(x : f32) -> f32 {\n return log(1.0 + x);\n}",clz32:"fn clz32(x : f32) -> f32 {\n return f32(countLeadingZeros(u32(x)));\n}"};t.exports={WebGPUKernel:class extends n{static get isSupported(){return l.isSupported}static get isAsync(){return!0}static isContextMatch(e){return Boolean(e&&"function"==typeof e.createShaderModule&&"function"==typeof e.createComputePipeline)}static getFeatures(){return d}static get features(){return d}static get mode(){return"webgpu"}static getSignature(e,t){return"webgpu"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static nativeFunctionArguments(){throw new Error("WebGPU backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebGPU backend does not yet support native functions")}static combineKernels(){throw new Error("WebGPU backend does not yet support combineKernels; chain kernels with `await` and pipeline mode instead")}constructor(e,t){if(super(e,t),t){if("unsigned"===t.precision&&!t.graphical)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(t.subKernels)throw new Error("WebGPU backend does not yet support createKernelMap")}this.mergeSettings(e.settings||t),(null===this.precision||this.graphical)&&(this.precision="single"),this.asyncMode=!0,this.threadDim=null,this.componentCount=1,this.compiledSource=null,this.translatedBody=null,this.translatedFunctions=null,this.paramsLayout=null,this._buildPromise=null,this._device=null,this.computePipeline=null,this.bindGroupLayout=null,this.bindGroup=null,this.bindGroupDirty=!0,this.paramsBuffer=null,this.paramsMirror=null,this.outputBuffer=null,this.argumentBuffers=null,this.constantBuffers=null,this.stagingPool=[],this._canvasContext=null,this._blitPipeline=null,this._blitParamsBuffer=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built){if(!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");if(t.length!==this.output.length)throw new Error("WebGPU backend does not yet support changing the output rank of a built kernel; the workgroup shape is fixed at build")}return this.output=t,this}toString(){throw new Error("WebGPU backend does not yet support toString")}validateSettings(e){if(this.graphical){if(!this.output||2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");if(this.pipeline)throw new Error("graphical mode and pipeline mode are mutually exclusive");if(!this.canvas)throw new Error("graphical mode requires a canvas (none could be created; pass one in settings)")}if("unsigned"===this.precision)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(this.precision="single",this.subKernels&&this.subKernels.length>0)throw new Error("WebGPU backend does not yet support createKernelMap");if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=Array.from(c.getDimensions(e[0]));else{if("WebGPUBuffer"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(e[0].output)}}this.checkOutput()}setupArguments(e){super.setupArguments(e);for(let e=0;e{this.translateSource(),this.paramsLayout=this.computeParamsLayout(),this.compiledSource=this.assembleWGSL()}),this.debug&&(console.log("WGSL Shader Output:"),console.log(this.compiledSource)),this.buildSignature(arguments),this._buildPromise=this._buildAsync()}translateSource(){const e=s.fromKernel(this,o),t=e.getPrototypes("kernel");if(this.translatedBody=t[t.length-1],this.translatedFunctions=t.slice(0,-1).join("\n"),this.graphical)this.componentCount=4;else switch(this.returnType||(this.returnType=e.getKernelResultType()),this.returnType){case"Number":case"Float":case"Integer":case"LiteralInteger":this.componentCount=1;break;case"Array(2)":this.componentCount=2;break;case"Array(3)":this.componentCount=3;break;case"Array(4)":this.componentCount=4;break;default:throw new Error(`WebGPU backend does not yet support returning ${this.returnType}`)}}computeParamsLayout(){const e=[],t=[];let n=16;for(let r=0;r,`);for(let e=0;e params : Params;");for(let t=0;t user_${e[t].name} : array;`);const i=1+e.length;r.push(`@group(0) @binding(${i}) var result : array;`),this.graphical&&r.push("fn kernelColor(index : i32, r : f32, g : f32, b : f32, a : f32) {\n result[index * 4] = r;\n result[index * 4 + 1] = g;\n result[index * 4 + 2] = b;\n result[index * 4 + 3] = a;\n}");for(let e=0;e constants_${n[e].name} : array;`);r.push("var threadGid : vec3;"),null!==this.paramsLayout.randomSeedOffset&&r.push("var pcgState : u32;\nfn pcg_random() -> f32 {\n pcgState = pcgState * 747796405u + 2891336453u;\n let word = ((pcgState >> ((pcgState >> 28u) + 4u)) ^ pcgState) * 277803737u;\n let mixed = (word >> 22u) ^ word;\n return f32(mixed >> 8u) / 16777216.0;\n}");const a=`${this.translatedFunctions}\n${this.translatedBody}`;/\bLOOP_MAX\b/.test(a)&&r.push(`const LOOP_MAX : i32 = ${parseInt(this.loopMaxIterations,10)||1e3};`);for(const e in f)new RegExp(`\\b${e}\\(`).test(a)&&r.push(f[e]);for(let t=0;t f32 {\n return user_${n}[u32(x + i32(params.user_${n}_dims.x) * (y + i32(params.user_${n}_dims.y) * z))];\n}`)}for(let e=0;e f32 {\n return constants_${t.name}[u32(x + ${i[0]} * (y + ${i[1]} * z))];\n}`)}this.translatedFunctions&&r.push(this.translatedFunctions);const o=1===this.output.length?[64,1,1]:[8,8,1];return this.workgroupSize=o,1===this.output.length?r.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n let flat_index : u32 = gid.x + gid.y * params.dispatchWidth;\n threadGid = vec3(flat_index, 0u, 0u);\n if (flat_index >= params.outputX) { return; }\n let data_index : i32 = i32(flat_index);\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`):r.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n threadGid = gid;\n if (gid.x >= params.outputX || gid.y >= params.outputY || gid.z >= params.outputZ) { return; }\n let data_index : i32 = i32(gid.x + params.outputX * (gid.y + params.outputY * gid.z));\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`),r.join("\n")}constantDimensions(e){const t=e instanceof p?Array.from(e.size):Array.from(c.getDimensions(e));for(;t.length<3;)t.push(1);return t}async _buildAsync(){const e=await l.acquire();this.context=e;const t=this._device=e.device,n=t.createShaderModule({code:this.compiledSource}),r=(await n.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(r.length>0)throw new Error("Error compiling WGSL compute shader:\n"+r.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n")+`\n--- generated WGSL ---\n${this.compiledSource}`);const{arrayArgs:s,bufferConstants:i,byteLength:a}=this.paramsLayout,o=[{binding:0,visibility:4,buffer:{type:"uniform"}}];for(let e=0;ei&&(s[1]=Math.ceil(s[0]/i),s[0]=Math.ceil(s[0]/s[1])),a=s[0]*t);for(let e=0;e<3;e++)if(s[e]>i)throw new Error(`output dimension ${e} needs ${s[e]} workgroups, over this device's limit of ${i}`);return{groups:s,dispatchWidth:a}}async _buildBlitPipeline(e){if(this.canvas.width=this.output[0],this.canvas.height=this.output[1],this._canvasContext=this.canvas.getContext("webgpu"),!this._canvasContext)throw new Error("could not get a webgpu context from the canvas");const t=navigator.gpu.getPreferredCanvasFormat();this._canvasContext.configure({device:e,format:t,alphaMode:"premultiplied"});const n=e.createShaderModule({code:"struct BlitParams { width : u32, height : u32, pad0 : u32, pad1 : u32 }\n@group(0) @binding(0) var blit : BlitParams;\n@group(0) @binding(1) var pixels : array;\n@vertex fn vs(@builtin(vertex_index) vi : u32) -> @builtin(position) vec4 {\n var pos = array, 3>(vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));\n return vec4(pos[vi], 0.0, 1.0);\n}\n@fragment fn fs(@builtin(position) pos : vec4) -> @location(0) vec4 {\n let x = u32(pos.x);\n let y = u32(pos.y);\n let row = blit.height - 1u - y;\n let i = (row * blit.width + x) * 4u;\n let a = pixels[i + 3u];\n return vec4(pixels[i] * a, pixels[i + 1u] * a, pixels[i + 2u] * a, a);\n}"}),r=(await n.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(r.length>0)throw new Error("Error compiling the graphical blit shader:\n"+r.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n"));this._blitBindGroupLayout=e.createBindGroupLayout({entries:[{binding:0,visibility:2,buffer:{type:"uniform"}},{binding:1,visibility:2,buffer:{type:"read-only-storage"}}]}),this._blitPipeline=e.createRenderPipeline({layout:e.createPipelineLayout({bindGroupLayouts:[this._blitBindGroupLayout]}),vertex:{module:n,entryPoint:"vs"},fragment:{module:n,entryPoint:"fs",targets:[{format:t}]},primitive:{topology:"triangle-list"}}),this._blitParamsBuffer=e.createBuffer({size:16,usage:72})}_ensureOutputBuffer(){const[e,t,n]=this.threadDim,r=e*t*n*4*this.componentCount;this.immutable&&this.pipeline&&this.outputBuffer&&(0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this.outputBuffer=null,this.bindGroupDirty=!0),this.outputBuffer&&this.outputBuffer.size>=r||(this.outputBuffer&&0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this._checkBufferSize(r,`output [${this.output.join(", ")}]`),this.outputBuffer=this._device.createBuffer({size:r,usage:132}),this.outputBuffer._refs=1,this.bindGroupDirty=!0)}_checkBufferSize(e,t){const n=this._device.limits,r=Math.min(n.maxStorageBufferBindingSize,n.maxBufferSize);if(e>r)throw new Error(`WebGPU backend: ${t} needs ${e} bytes but this device allows ${r} per storage buffer (maxStorageBufferBindingSize/maxBufferSize); reduce the output or split the work across kernels`)}_snapshotArguments(e){const t=new Array(e.length);for(let n=0;nthis._runInternal(e))}_runInternal(e){if(this.context&&this.context.isLost)throw new Error("WebGPU device was lost; call kernel.destroy() (or gpu.destroy()) and run again to rebuild on a fresh device");const t=this._device,n=t.queue,{arrayArgs:r,scalarArgs:s,bufferConstants:i}=this.paramsLayout,a=this.threadDim=Array.from(this.output);for(;a.length<3;)a.push(1);if(this._ensureOutputBuffer(),null!==this.paramsLayout.randomSeedOffset){const e=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0;this.paramsU32[this.paramsLayout.randomSeedOffset/4]=e}this.paramsU32[0]=a[0],this.paramsU32[1]=a[1],this.paramsU32[2]=a[2],this.paramsU32[3]=this._computeDispatch(a).dispatchWidth;for(let s=0;s{const e=new Float32Array(p.buffer.getMappedRange(0,u).slice(0));return p.buffer.unmap(),this._releaseStaging(p),this._shapeOutput(e,d,this.componentCount)},e=>{throw this._releaseStaging(p),e})}_acquireStaging(e){for(let t=0;t=e)return n.busy=!0,n}const t={buffer:this._device.createBuffer({size:e,usage:9}),size:e,busy:!0,pooled:this.stagingPool.length<3};return t.pooled&&this.stagingPool.push(t),t}_releaseStaging(e){e.pooled?e.busy=!1:e.buffer.destroy()}_shapeOutput(e,t,n){const[r,s,i]=[t[0],t[1]||1,t[2]||1];if(1===n)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,r);case 2:return c.erectMemoryOptimized2DFloat(e,r,s);default:return c.erectMemoryOptimized3DFloat(e,r,s,i)}const a=n,o=t=>{const n=new Array(r);for(let s=0;s{const t=new Float32Array(i.buffer.getMappedRange(0,s).slice(0));return i.buffer.unmap(),this._releaseStaging(i),this._shapeOutput(t,n,e.componentCount)},e=>{throw this._releaseStaging(i),e})}getPixels(e){if(!this.graphical)return Promise.reject(new Error("getPixels only works on a graphical kernel"));if(!this.outputBuffer)return Promise.reject(new Error("run the kernel before reading its pixels"));const[t,n]=this.output,r=t*n*4*4,s=this._acquireStaging(r),i=this._device.createCommandEncoder();return i.copyBufferToBuffer(this.outputBuffer,0,s.buffer,0,r),this._device.queue.submit([i.finish()]),s.buffer.mapAsync(1,0,r).then(()=>{const i=new Float32Array(s.buffer.getMappedRange(0,r).slice(0));s.buffer.unmap(),this._releaseStaging(s);const a=new Uint8ClampedArray(t*n*4);for(let r=0;r{throw this._releaseStaging(s),e})}destroy(e){if(this._blitParamsBuffer&&(this._blitParamsBuffer.destroy(),this._blitParamsBuffer=null),this._canvasContext&&(this._canvasContext.unconfigure(),this._canvasContext=null),this._blitPipeline=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null,this.paramsBuffer&&(this.paramsBuffer.destroy(),this.paramsBuffer=null),this.paramsLayout)for(let e=0;e{const n={i32:127,i64:126,f32:125,f64:124,v128:123},r=new DataView(new ArrayBuffer(16));function s(e,t){let n=e>>>0;do{let e=127&n;n>>>=7,0!==n&&(e|=128),t.push(e)}while(0!==n)}function i(e,t){let n=0|e;for(;;){const e=127&n;if(n>>=7,0===n&&!(64&e)||-1===n&&64&e)return void t.push(e);t.push(128|e)}}function a(e,t,n){let r=e>>>0;for(let e=0;e<4;e++)t[n+e]=127&r|128,r>>>=7;t[n+4]=127&r}function o(e,t){const n=[];for(let t=0;t65535&&t++,r<128?n.push(r):r<2048?n.push(192|r>>6,128|63&r):r<65536?n.push(224|r>>12,128|r>>6&63,128|63&r):n.push(240|r>>18,128|r>>12&63,128|r>>6&63,128|63&r)}s(n.length,t);for(let e=0;e3)throw new Error(`WasmModuleBuilder: lane index ${t} out of range for 4-lane shape`);return this.bytes.push(253,e,t),this}_push(e){for(let t=0;t${t.join(",")}`;if(n in this.typeIndexByKey)return this.typeIndexByKey[n];const r=this.types.length;return this.types.push({params:e,results:t}),this.typeIndexByKey[n]=r,r}addMemoryImport(e,t,n=!1){if(n&&null==t)throw new Error("WasmModuleBuilder: shared memory import requires a maximum");return this.memoryImport={initial:e,maximum:t,shared:n},this}addFuncImport(e,t,n,r="env"){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);const s=this.funcImports.length;return this.funcImports.push({name:e,module:r,typeIndex:this._typeIndex(t,n)}),this.funcImportIndexByName[e]=s,s}addGlobal(e,t,n){return u(e),this.globals.push({type:e,mutable:t,initialValue:n}),this.globals.length-1}addFunction(e,{params:t=[],results:n=[],locals:r=[]}={}){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);t.forEach(u),n.forEach(u),r.forEach(u);const s=new h(this,e,t,n,r);return this.functionIndexByName[e]=this.functions.length,this.functions.push({name:e,emitter:s,typeIndex:this._typeIndex(t,n)}),s}exportFunction(e,t=e){return this.exports.push({name:e,exportName:t}),this}_resolveFuncIndex(e){if(e in this.funcImportIndexByName)return this.funcImportIndexByName[e];if(e in this.functionIndexByName)return this.funcImports.length+this.functionIndexByName[e];throw new Error(`WasmModuleBuilder: call target "${e}" is not an import or a defined function`)}_section(e,t,n){n.push(e),s(t.length,n);for(let e=0;e0){const t=[];s(this.types.length,t);for(const{params:e,results:n}of this.types){t.push(96),s(e.length,t);for(const n of e)t.push(u(n));s(n.length,t);for(const e of n)t.push(u(e))}this._section(1,t,e)}if(null!==this.memoryImport||this.funcImports.length>0){const t=[];if(s((null!==this.memoryImport?1:0)+this.funcImports.length,t),null!==this.memoryImport){const{initial:e,maximum:n,shared:r}=this.memoryImport;o("env",t),o("memory",t),t.push(2);const i=null!=n;t.push(r?3:i?1:0),s(e,t),i&&s(n,t)}for(const{name:e,module:n,typeIndex:r}of this.funcImports)o(n,t),o(e,t),t.push(0),s(r,t);this._section(2,t,e)}if(this.functions.length>0){const t=[];s(this.functions.length,t);for(const{typeIndex:e}of this.functions)s(e,t);this._section(3,t,e)}if(this.globals.length>0){const t=[];s(this.globals.length,t);for(const{type:e,mutable:n,initialValue:s}of this.globals){if(t.push(u(e),n?1:0),"i32"===e)t.push(65),i(s,t);else if("f32"===e){t.push(67),r.setFloat32(0,s,!0);for(let e=0;e<4;e++)t.push(r.getUint8(e))}else{if("v128"!==e)throw new Error(`WasmModuleBuilder: no initializer encoding for global type "${e}"`);t.push(253,12);for(let e=0;e<16;e++)t.push(0)}t.push(11)}this._section(6,t,e)}if(this.exports.length>0){const t=[];s(this.exports.length,t);for(const{name:e,exportName:n}of this.exports)o(n,t),t.push(0),s(this._resolveFuncIndex(e),t);this._section(7,t,e)}if(this.functions.length>0){const t=[];s(this.functions.length,t);for(const{emitter:e}of this.functions){const n=e.bytes.slice();for(const{at:t,name:r}of e.callFixups)a(this._resolveFuncIndex(r),n,t);const r=[],i=[];for(const t of e.locals){const e=u(t);i.length>0&&i[i.length-1].type===e?i[i.length-1].count++:i.push({type:e,count:1})}s(i.length,r);for(const{type:e,count:t}of i)s(t,r),r.push(e);for(let e=0;e{const{utils:n}=i(),{FunctionNode:r}=h(),{WasmFunctionEmitter:s}=at();var a=class{constructor(){this.localCount=0}addLocal(){return this.localCount++}};for(const e of Object.getOwnPropertyNames(s.prototype))"constructor"!==e&&"addLocal"!==e&&"function"==typeof s.prototype[e]&&(a.prototype[e]=function(){return this});const o={sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,sinh:1,cosh:1,tanh:1,asinh:1,acosh:1,atanh:1,exp:1,expm1:1,log:1,log2:1,log10:1,log1p:1,cbrt:1,pow:2,sign:1},u={abs:"f32Abs",floor:"f32Floor",ceil:"f32Ceil",sqrt:"f32Sqrt",trunc:"f32Trunc"},l={"+":"f32Add","-":"f32Sub","*":"f32Mul"},c={"+":"i32Add","-":"i32Sub","*":"i32Mul"},p={"==":"f32Eq","===":"f32Eq","!=":"f32Ne","!==":"f32Ne","<":"f32Lt",">":"f32Gt","<=":"f32Le",">=":"f32Ge"},d={"==":"i32Eq","===":"i32Eq","!=":"i32Ne","!==":"i32Ne","<":"i32LtS",">":"i32GtS","<=":"i32LeS",">=":"i32GeS"},f={"&":"i32And","|":"i32Or","^":"i32Xor","<<":"i32Shl",">>":"i32ShrS",">>>":"i32ShrU"},m={"+":"f32x4Add","-":"f32x4Sub","*":"f32x4Mul"},g={"+":"i32x4Add","-":"i32x4Sub","*":"i32x4Mul"},y={"==":"f32x4Eq","===":"f32x4Eq","!=":"f32x4Ne","!==":"f32x4Ne","<":"f32x4Lt",">":"f32x4Gt","<=":"f32x4Le",">=":"f32x4Ge"},x={"==":"i32x4Eq","===":"i32x4Eq","!=":"i32x4Ne","!==":"i32x4Ne","<":"i32x4LtS",">":"i32x4GtS","<=":"i32x4LeS",">=":"i32x4GeS"},b={"<<":"i32x4Shl",">>":"i32x4ShrS",">>>":"i32x4ShrU"},v={abs:"f32x4Abs",floor:"f32x4Floor",ceil:"f32x4Ceil",sqrt:"f32x4Sqrt",trunc:"f32x4Trunc"};function S(e){switch(e){case"Number":case"Float":case"LiteralInteger":return"f32";case"Integer":case"Boolean":return"i32";default:throw new Error(`WebAssembly backend does not yet support ${e} arguments to helper functions`)}}t.exports={WebAssemblyFunctionNode:class extends r{get readsCanFault(){return!0}get readsFaultAtOneLevel(){return!0}constructor(e,t){super(e,t),this.assembler=null,this.em=null,this.locals=null,this.depth=0,this.loopStack=null,this.usedMathImports=new Set,this.usesRandom=!1,this.readsThread=!1,this.taintedLocals=null,this.uniformity=[],this._analysisDone=!1,this._analysisPass=!1,this.vec=!1,this.vMaskDepth=0,this.vCur=-1,this.vRetMask=-1,this.vTerminated=!1,this.vInfo=null,this._vBaseX=-1}mangleFunctionName(e){return`fn_${n.sanitizeName(e)}`}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}toString(){return this._analysisDone||(this._analysisDone=!0,this._analysisPass=!0,this.walkFunction(new a),this._analysisPass=!1),""}emitFunction(e){this.assembler=e;const{module:t}=e;let n;if(this.isRootKernel)n=t.addFunction("kernel",{params:[],results:[]});else{const e=this.argumentTypes.map(e=>S("LiteralInteger"===e?"Number":e)),r=[];if(this.returnType)switch(this.returnType){case"Integer":case"Boolean":r.push("i32");break;case"Number":case"Float":case"LiteralInteger":r.push("f32");break;default:throw new Error(`WebAssembly backend does not yet support helper functions returning ${this.returnType}`)}n=t.addFunction(this.mangleFunctionName(this.name),{params:e,results:r})}return this.walkFunction(n),!this.isRootKernel&&this.returnType&&n.unreachable(),n}walkFunction(e){this.em=e,this.locals=new Map,this.depth=0,this.loopStack=[],this.taintedLocals=new Set;const t=this.getJsAST();if(this.isRootKernel)for(const n of this.collectAssignedArgumentNames(t)){const t=this.argumentNames.indexOf(n),r=this.argumentTypes[t];if("Number"!==r&&"Float"!==r&&"Integer"!==r&&"Boolean"!==r)continue;const s=this.assembler?this.assembler.layout.scalars[n]:null,i=s?s.offset:0,a="Integer"===r||"Boolean"===r?"i32":"f32",o=e.addLocal(a);e.i32Const(0),"i32"===a?e.i32Load(i):e.f32Load(i),e.localSet(o),this.locals.set(n,{kind:"scalar",index:o,wtype:a,gtype:r})}if(!this.isRootKernel){for(let e=0;e{if(r&&"object"==typeof r){if(Array.isArray(r))return r.forEach(n);if("FunctionDeclaration"!==r.type||r===e){"AssignmentExpression"===r.type&&"Identifier"===r.left.type&&-1!==this.argumentNames.indexOf(r.left.name)&&t.add(r.left.name),"UpdateExpression"===r.type&&"Identifier"===r.argument.type&&-1!==this.argumentNames.indexOf(r.argument.name)&&t.add(r.argument.name);for(const e in r){if("loc"===e||"start"===e||"end"===e||"parent"===e)continue;const t=r[e];t&&"object"==typeof t&&n(t)}}}};return n(e.body),t}enterBlock(e){this.em.block(e),this.depth++}enterLoop(e){this.em.loop(e),this.depth++}enterIf(e){this.em.if_(e),this.depth++}exit(){this.em.end(),this.depth--}brTo(e){this.em.br(this.depth-e)}brIfTo(e){this.em.brIf(this.depth-e)}get loopMax(){return parseInt(this.loopMaxIterations,10)||1e3}coerce(e,t){if(e===t)return t;if("void"===e)throw new Error("cannot use a void expression as a value");switch(t){case"f32":return this.em.f32ConvertI32S(),"f32";case"i32":return"f32"===e&&this.em.i32TruncSatF32S(),"i32";case"bool":return"f32"===e?this.em.f32Const(0).f32Ne():this.em.i32Eqz().i32Eqz(),"bool";default:throw new Error(`unknown wasm value category ${t}`)}}castLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castLiteralToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}castValueToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castValueToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}emitByType(e,t){const n=this.getType(e);return"f32"===t?"Integer"===n?this.castValueToFloat(e):"LiteralInteger"===n?this.castLiteralToFloat(e):(this.coerce(this.expression(e),"f32"),"f32"):"Number"===n||"Float"===n?this.castValueToInteger(e):"LiteralInteger"===n?this.castLiteralToInteger(e):(this.coerce(this.expression(e),"i32"),"i32")}emitCondition(e){const t=this.expression(e);if("bool"!==t)if("i32"!==t){if("f32"!==t)throw this.astErrorOutput("cannot use a void expression as a condition",e);this.em.f32Const(0).f32Ne()}else this.em.i32Eqz().i32Eqz()}statement(e){switch(e.type){case"VariableDeclaration":return this.stmtVariableDeclaration(e);case"ExpressionStatement":return this.statementExpression(e.expression);case"ReturnStatement":return this.stmtReturn(e);case"IfStatement":return this.stmtIf(e);case"ForStatement":return this.stmtFor(e);case"WhileStatement":return this.stmtWhile(e);case"DoWhileStatement":return this.stmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.castValueToFloat(s));else switch(i.valueType=u,u){case"Number":case"Float":this.setScalarLocal(o,"f32",u,()=>{"LiteralInteger"===a?this.castLiteralToFloat(s):"Integer"===a?this.castValueToFloat(s):this.coerce(this.expression(s),"f32")});break;case"Integer":this.setScalarLocal(o,"i32","Integer",()=>{"LiteralInteger"===a?this.castLiteralToInteger(s):"Number"===a||"Float"===a?this.castValueToInteger(s):this.coerce(this.expression(s),"i32")});break;case"Boolean":this.setScalarLocal(o,"i32","Boolean",()=>this.emitCondition(s));break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${u}`,e)}this.isThreadDependent(s)&&this.taintedLocals.add(o)}}setScalarLocal(e,t,n,r){let s=this.locals.get(e);s&&"scalar"===s.kind&&s.wtype===t?s.gtype=n:(s={kind:"scalar",index:this.em.addLocal(t),wtype:t,gtype:n},this.locals.set(e,s)),r(),this.em.localSet(s.index)}declareVecLocal(e,t,n,r,s){const i=parseInt(t.substring(6),10);r.valueType=t;let a=this.locals.get(e);if(!a||"vec"!==a.kind||a.n!==i){const n=[];for(let e=0;ethis.em.localSet(n.index);else{if(n||!this.isRootKernel||-1===this.argumentNames.indexOf(t))throw this.astErrorOutput(`cannot assign to "${t}"`,e);{const n=this.argumentTypes[this.argumentNames.indexOf(t)],i=this.assembler?this.assembler.layout.scalars[t]:null;if(this.assembler&&!i)throw this.astErrorOutput(`WebAssembly backend does not yet support assigning to the array argument "${t}"`,e);const a=i?i.offset:0;r="Integer"===n||"Boolean"===n?"i32":"f32",this.em.i32Const(0),s=()=>"i32"===r?this.em.i32Store(a):this.em.f32Store(a)}}if("="===e.operator){const t=this.getType(e.left),n=this.getType(e.right);"Integer"!==t&&"Integer"===n?(this.castValueToFloat(e.right),this.coerce("f32",r)):"Integer"!==t&&"LiteralInteger"===n?(this.castLiteralToFloat(e.right),this.coerce("f32",r)):"Integer"===t&&"LiteralInteger"===n?(this.castLiteralToInteger(e.right),this.coerce("i32",r)):"Integer"!==t||"Number"!==n&&"Float"!==n?this.coerce(this.expression(e.right),r):(this.castValueToInteger(e.right),this.coerce("i32",r))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.coerce(this.exprBinary(t),r)}s(),(this.isThreadDependent(e.right)||"="!==e.operator&&this.taintedLocals.has(t))&&this.taintedLocals.add(t)}emitUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const n=this.locals.get(e.argument.name);if(!n||"scalar"!==n.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const r="i32"===n.wtype,s=()=>r?this.em.i32Const(1):this.em.f32Const(1),i="++"===e.operator?r?"i32Add":"f32Add":r?"i32Sub":"f32Sub";return t?(this.em.localGet(n.index),s(),this.em[i]().localSet(n.index),"void"):(e.prefix?(this.em.localGet(n.index),s(),this.em[i]().localTee(n.index)):(this.em.localGet(n.index).localGet(n.index),s(),this.em[i]().localSet(n.index)),n.wtype)}stmtReturn(e){if(!e.argument){if(this.isRootKernel)return void this.em.return_();throw this.astErrorOutput("Unexpected return statement",e)}this.pushState("skip-literal-correction");const t=this.getType(e.argument);if(this.popState("skip-literal-correction"),this.returnType||(this.returnType="LiteralInteger"===t||"Integer"===t?"Number":t),this.isRootKernel)return this.stmtRootReturn(e,t);if(this.isSubKernel)throw this.astErrorOutput("WebAssembly backend does not yet support createKernelMap",e);switch(this.returnType){case"LiteralInteger":case"Number":case"Float":"Integer"===t?this.castValueToFloat(e.argument):"LiteralInteger"===t?this.castLiteralToFloat(e.argument):this.coerce(this.expression(e.argument),"f32");break;case"Integer":"Float"===t||"Number"===t?this.castValueToInteger(e.argument):"LiteralInteger"===t?this.castLiteralToInteger(e.argument):this.coerce(this.expression(e.argument),"i32");break;case"Boolean":this.emitCondition(e.argument);break;default:throw this.astErrorOutput(`unhandled return type ${this.returnType}`,e)}this.em.return_()}stmtRootReturn(e,t){const n=this.assembler?this.assembler.globals:{dataIndex:0},r=this.assembler?this.assembler.layout.outputOffset:0;switch(this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const t=parseInt(this.returnType.substring(6),10),s=e.argument;if("ArrayExpression"===s.type){if(s.elements.length!==t)throw this.astErrorOutput(`expected ${t} array elements to match return type ${this.returnType}`,e);for(let e=0;e1&&(t=!1);for(let e=0;e{if(e===a.length)return o&&this.emitSwitchConsequent(o),!1;const{tests:t,consequent:n}=a[e];for(let e=0;e0&&this.em.i32Or();return this.enterIf(),this.emitSwitchConsequent(n),(e+10&&(n.push({tests:r,consequent:e[s].consequent}),r=[])):t=e[s].consequent;return{groups:n,defaultConsequent:t}}collectSwitchCaseStatements(e){const t=[];for(let n=0;n{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(n);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&n(e[t]))return!0;return!1};for(let e=0;e{const n=this.getType(t);switch(r){case"Number":case"Float":"Integer"===n?this.castValueToFloat(t):"LiteralInteger"===n?this.castLiteralToFloat(t):this.coerce(this.expression(t),"f32");break;case"Integer":"Number"===n||"Float"===n?this.castValueToInteger(t):"LiteralInteger"===n?this.castLiteralToInteger(t):this.coerce(this.expression(t),"i32");break;case"Boolean":this.emitCondition(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${r}`,e)}};return this.emitCondition(e.test),this.enterIf(s),i(e.consequent),this.em.else_(),i(e.alternate),this.exit(),"Boolean"===r?"bool":s}exprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const n=this.isAstMathFunction(e);if(t=n||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);if(this.calledFunctions.indexOf(t)<0&&this.calledFunctions.push(t),this.onFunctionCall&&this.onFunctionCall(this.name,t,e.arguments),n)return this.emitMathCall(t,e);const r=this.getType(e),s=this.lookupFunctionArgumentTypes(t)||[];for(let n=0;n{switch(this.getType(e)){case"Integer":this.castValueToFloat(e);break;case"LiteralInteger":this.castLiteralToFloat(e);break;default:this.coerce(this.expression(e),"f32")}},r=u[e];if(r)return n(t.arguments[0]),this.em[r](),"f32";switch(e){case"round":return n(t.arguments[0]),this.em.f32Const(.5).f32Add().f32Floor(),"f32";case"fround":return n(t.arguments[0]),"f32";case"min":case"max":{const r="min"===e?"f32Min":"f32Max";n(t.arguments[0]);for(let e=1;e0&&this.emitClampScalarIndex(a.dims[0]*a.dims[1]*a.dims[2]-1),this.em.i32Const(2).i32Shl(),this.em.f32Load(a.offset),"f32"}emitClampScalarIndex(e){const t=this.em.addLocal("i32");this.em.localSet(t),this.em.localGet(t).i32Const(0).localGet(t).i32Const(0).i32GeS().select(),this.em.localSet(t),this.em.localGet(t).i32Const(e).localGet(t).i32Const(e).i32LeS().select()}emitVecIndex(e,t){if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return this.em.localGet(e.indices[t.value]),"f32"}const n=this.em.addLocal("i32");this.emitIndex(t),this.em.localSet(n),this.em.localGet(e.indices[0]);for(let t=1;t{if(!e||"object"!=typeof e)return!1;switch(e.type){case"Literal":case"ThisExpression":return!1;case"Identifier":return t.has(e.name);case"MemberExpression":return e.computed||"MemberExpression"!==e.object.type||e.object.computed||!e.object.property||"thread"!==e.object.property.name?e.computed?a(e.object)||a(e.property):a(e.object):"x"===e.property.name;case"BinaryExpression":case"LogicalExpression":return a(e.left)||a(e.right);case"UnaryExpression":case"UpdateExpression":return a(e.argument);case"ConditionalExpression":return a(e.test)||a(e.consequent)||a(e.alternate);case"CallExpression":return!i.isAstMathFunction(e)||("random"===e.callee.property.name||e.arguments.some(a));case"SequenceExpression":return e.expressions.some(a);case"ArrayExpression":return e.elements.some(a);case"AssignmentExpression":return a(e.right)||"Identifier"===e.left.type&&t.has(e.left.name);default:return!0}},o=e=>{e&&!t.has(e)&&(t.add(e),s=!0)},u=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>u(e,t));switch(e.type){case"UpdateExpression":return"Identifier"===e.argument.type&&(-1!==i.argumentNames.indexOf(e.argument.name)&&(n.has(e.argument.name)||(n.add(e.argument.name),s=!0),o(e.argument.name)),t&&o(e.argument.name)),u(e.argument,t);case"AssignmentExpression":return"Identifier"===e.left.type&&(-1!==i.argumentNames.indexOf(e.left.name)&&(n.has(e.left.name)||(n.add(e.left.name),s=!0),o(e.left.name)),t&&o(e.left.name)),u(e.left,t),u(e.right,t);case"ConditionalExpression":{u(e.test,t);const n=t||a(e.test);return u(e.consequent,n),u(e.alternate,n)}case"LogicalExpression":return u(e.left,t),u(e.right,!0);default:for(const n in e){if("loc"===n||"start"===n||"end"===n||"parent"===n)continue;const r=e[n];r&&"object"==typeof r&&u(r,t)}}}},l=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>l(e,t));switch(e.type){case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.push(e.id.name);break;case"AssignmentExpression":"Identifier"===e.left.type&&t.push(e.left.name);break;case"UpdateExpression":"Identifier"===e.argument.type&&t.push(e.argument.name);break;case"FunctionDeclaration":return}for(const n in e){if("loc"===n||"start"===n||"end"===n||"parent"===n)continue;const r=e[n];r&&"object"==typeof r&&l(r,t)}}},h=(e,t)=>{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>h(e,t));switch(e.type){case"BreakStatement":case"ContinueStatement":return t;case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return!1;case"IfStatement":{const n=t||a(e.test);return!!h(e.consequent,n)||!!e.alternate&&h(e.alternate,n)}case"ConditionalExpression":{const n=t||a(e.test);return h(e.consequent,n)||h(e.alternate,n)}case"SwitchStatement":{const n=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));return e.cases.some(e=>e.consequent.some(e=>"BreakStatement"!==e.type&&h(e,n)))}default:for(const n in e){if("loc"===n||"start"===n||"end"===n||"parent"===n)continue;const r=e[n];if(r&&"object"==typeof r&&h(r,t))return!0}return!1}},c=(e,r)=>{switch(e.type){case"AssignmentExpression":if("Identifier"===e.left.type){const u=e.left.name;-1!==i.argumentNames.indexOf(u)&&(n.has(u)||(n.add(u),s=!0),o(u)),(r||a(e.right)||"="!==e.operator&&t.has(u))&&o(u)}return u(e.right,r);case"UpdateExpression":if("Identifier"===e.argument.type){const t=e.argument.name;-1!==i.argumentNames.indexOf(t)&&(n.has(t)||(n.add(t),s=!0),o(t)),r&&o(t)}return;case"SequenceExpression":return e.expressions.forEach(e=>c(e,r));default:return u(e,r)}},p=(e,t)=>{if(e)switch(e.type){case"VariableDeclaration":for(const n of e.declarations)n.init&&((t||a(n.init))&&o(n.id.name),u(n.init,t));return;case"ExpressionStatement":return c(e.expression,t);case"ReturnStatement":return t&&(r=!0),void(e.argument&&u(e.argument,t));case"IfStatement":{u(e.test,t);const n=t||a(e.test);return p(e.consequent,n),void(e.alternate&&p(e.alternate,n))}case"ForStatement":case"WhileStatement":case"DoWhileStatement":{const n=t||!!e.test&&a(e.test)||h(e.body,!1);if(n){const t=[];e.init&&l(e.init,t),l(e.body,t),e.update&&l(e.update,t),t.forEach(o)}return e.init&&("VariableDeclaration"===e.init.type?p(e.init,t):c(e.init,t)),p(e.body,n),e.update&&c(e.update,n),void(e.test&&u(e.test,n))}case"SwitchStatement":{const n=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));for(const t of e.cases)for(const e of t.consequent)p(e,n);return}case"BlockStatement":return e.body.forEach(e=>p(e,t));default:return}};for(;s;)s=!1,p(e.body,!1);return{varying:t,varyingReturn:r,assignedArgs:n,exprVarying:a,hasVaryingExit:h}}vZero(){return this.em.v128ConstI32x4(0,0,0,0),this}vInnermostVaryingLoop(){const e=this.vLoopStack[this.vLoopStack.length-1];return e&&e.varying?e:null}vRecomputeCur(e){const t=this.em;t.localGet(e),-1!==this.vRetMask&&t.localGet(this.vRetMask).v128Andnot();const n=this.vInnermostVaryingLoop();n&&(-1!==n.vBrk&&t.localGet(n.vBrk).v128Andnot(),-1!==n.vCnt&&t.localGet(n.vCnt).v128Andnot()),t.localSet(this.vCur)}vLoopBodyExits(e){let t=!1,n=!1;const r=e=>{if(!(!e||"object"!=typeof e||t&&n)){if(Array.isArray(e))return e.forEach(r);switch(e.type){case"BreakStatement":return void(t=!0);case"ContinueStatement":return void(n=!0);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return;case"SwitchStatement":for(const t of e.cases)for(const e of t.consequent)"BreakStatement"!==e.type&&r(e);return}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const n=e[t];n&&"object"==typeof n&&r(n)}}};return r(e),{hasBreak:t,hasContinue:n}}vSetLocal(e){const t=this.em;this.vMaskDepth>0&&t.localGet(e).localGet(this.vCur).v128Bitselect(),t.localSet(e)}vCoerce(e,t){if(e===t)return t;const n=this.em;switch(e){case"f32":case"i32":case"bool":if("vf32"===t)return this.coerce(e,"f32"),n.f32x4Splat(),t;if("vi32"===t)return this.coerce(e,"i32"),n.i32x4Splat(),t;if("vbool"===t)return this.coerce(e,"i32"),n.i32x4Splat(),this.vZero(),n.i32x4Ne(),t;break;case"vf32":if("vi32"===t)return n.i32x4TruncSatF32x4S(),t;if("vbool"===t)return n.v128ConstF32x4(0,0,0,0).f32x4Ne(),t;break;case"vi32":if("vf32"===t)return n.f32x4ConvertI32x4S(),t;if("vbool"===t)return this.vZero(),n.i32x4Ne(),t;break;case"vbool":if("vi32"===t)return n.v128ConstI32x4(1,1,1,1).v128And(),t;if("vf32"===t)return n.v128ConstI32x4(1,1,1,1).v128And().f32x4ConvertI32x4S(),t}throw new Error(`cannot convert ${e} to ${t}`)}vCastLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastLiteralToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vCastValueToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastValueToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vEmitByType(e,t){const n=this.getType(e);return"vf32"===t?"Integer"===n?this.vCastValueToFloat(e):"LiteralInteger"===n?this.vCastLiteralToFloat(e):(this.vCoerce(this.vexpr(e),"vf32"),"vf32"):"Number"===n||"Float"===n?this.vCastValueToInteger(e):"LiteralInteger"===n?this.vCastLiteralToInteger(e):(this.vCoerce(this.vexpr(e),"vi32"),"vi32")}vexprMask(e){const t=this.vexpr(e);if("vbool"!==t)return"vi32"===t?(this.vZero(),void this.em.i32x4Ne()):void("vf32"!==t?(this.coerce(t,"bool"),this.em.i32x4Splat(),this.vZero(),this.em.i32x4Ne()):this.em.v128ConstF32x4(0,0,0,0).f32x4Ne())}vstatement(e){switch(e.type){case"VariableDeclaration":return this.vstmtVariableDeclaration(e);case"ExpressionStatement":return this.vstatementExpression(e.expression);case"ReturnStatement":return this.vstmtReturn(e);case"IfStatement":return this.vstmtIf(e);case"ForStatement":return this.vstmtFor(e);case"WhileStatement":return this.vstmtWhile(e);case"DoWhileStatement":return this.vstmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.vCastValueToFloat(r));switch(i.valueType=o,o){case"Number":case"Float":this.vSetVaryingScalar(s,"vf32",o,()=>{"LiteralInteger"===a?this.vCastLiteralToFloat(r):"Integer"===a?this.vCastValueToFloat(r):this.vCoerce(this.vexpr(r),"vf32")});break;case"Integer":this.vSetVaryingScalar(s,"vi32","Integer",()=>{"LiteralInteger"===a?this.vCastLiteralToInteger(r):"Number"===a||"Float"===a?this.vCastValueToInteger(r):this.vCoerce(this.vexpr(r),"vi32")});break;case"Boolean":this.vSetVaryingScalar(s,"vi32","Boolean",()=>{this.vexprMask(r),this.em.v128ConstI32x4(1,1,1,1).v128And()});break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${o}`,t)}}vSetVaryingScalar(e,t,n,r){let s=this.locals.get(e);s&&"vscalar"===s.kind&&s.wtype===t?s.gtype=n:(s={kind:"vscalar",index:this.em.addLocal("v128"),wtype:t,gtype:n},this.locals.set(e,s)),r(),this.vSetLocal(s.index)}vEmitArrayElement(e){switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}}vAssign(e){if("Identifier"!==e.left.type)throw this.astErrorOutput(`WebAssembly backend does not yet support assignment to ${e.left.type}`,e);const t=e.left.name,n=this.locals.get(t);if(n&&"scalar"===n.kind)return this.emitAssignment(e);if(!n||"vscalar"!==n.kind)throw this.astErrorOutput(`cannot assign to "${t}"`,e);const r=n.wtype;if("="===e.operator){const t=this.getType(e.left),n=this.getType(e.right);"Integer"!==t&&"Integer"===n?(this.vCastValueToFloat(e.right),this.vCoerce("vf32",r)):"Integer"!==t&&"LiteralInteger"===n?(this.vCastLiteralToFloat(e.right),this.vCoerce("vf32",r)):"Integer"===t&&"LiteralInteger"===n?(this.vCastLiteralToInteger(e.right),this.vCoerce("vi32",r)):"Integer"!==t||"Number"!==n&&"Float"!==n?this.vCoerce(this.vexpr(e.right),r):(this.vCastValueToInteger(e.right),this.vCoerce("vi32",r))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.vCoerce(this.vexprBinary(t),r)}this.vSetLocal(n.index)}vUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const n=this.locals.get(e.argument.name);if(n&&"scalar"===n.kind)return this.emitUpdate(e,t);if(!n||"vscalar"!==n.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const r=this.em,s="vi32"===n.wtype,i=()=>s?r.v128ConstI32x4(1,1,1,1):r.v128ConstF32x4(1,1,1,1),a="++"===e.operator?s?"i32x4Add":"f32x4Add":s?"i32x4Sub":"f32x4Sub";if(t)return r.localGet(n.index),i(),r[a](),this.vSetLocal(n.index),"void";if(e.prefix)r.localGet(n.index),i(),r[a](),this.vSetLocal(n.index),r.localGet(n.index);else{const e=r.addLocal("v128");r.localGet(n.index).localSet(e),r.localGet(n.index),i(),r[a](),this.vSetLocal(n.index),r.localGet(e)}return n.wtype}vstmtIf(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementBody(e.consequent),e.alternate&&(t.else_(),this.vstatementBody(e.alternate)),void this.exit();const n=t.addLocal("v128");this.vexprMask(e.test),t.localSet(n);const r=t.addLocal("v128");t.localGet(this.vCur).localSet(r),t.localGet(r).localGet(n).v128And().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.consequent),this.vMaskDepth--,this.exit(),e.alternate&&(t.localGet(r).localGet(n).v128Andnot().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.alternate),this.vMaskDepth--,this.exit()),this.vRecomputeCur(r)}vstmtReturn(e){const t=this.em;if(!e.argument)return void this.vRetireOrReturn();this.pushState("skip-literal-correction");const n=this.getType(e.argument);switch(this.popState("skip-literal-correction"),this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const n=parseInt(this.returnType.substring(6),10),r=e.argument,s=[];if("ArrayExpression"===r.type){if(r.elements.length!==n)throw this.astErrorOutput(`expected ${n} array elements to match return type ${this.returnType}`,e);for(let e=0;e0?i=this.vCur:-1!==this.vRetMask&&(i=t.addLocal("v128"),t.localGet(this.vRetMask).v128Not().localSet(i));const a=t.addLocal("i32");if(1===s)return t.globalGet(n.dataIndex).i32Const(2).i32Shl().localSet(a),void(-1===i?t.localGet(a).localGet(e[0]).v128Store(r,2):(t.localGet(a),t.localGet(e[0]),t.localGet(a).v128Load(r,2),t.localGet(i).v128Bitselect(),t.v128Store(r,2)));t.globalGet(n.dataIndex).i32Const(s).i32Mul().i32Const(2).i32Shl().localSet(a);for(let n=0;n<4;n++)for(let o=0;oe.test&&this.vInfo.exprVarying(e.test)),i=this.getType(t);if(!s){let s,a;switch(i){case"Float":case"Number":a=!1,s=r.addLocal("f32"),this.coerce(this.expression(t),"f32"),r.localSet(s);break;case"Integer":a=!0,s=r.addLocal("i32"),this.coerce(this.expression(t),"i32"),r.localSet(s);break;case"LiteralInteger":a=!0,s=r.addLocal("i32"),this.castLiteralToInteger(t),r.localSet(s);break;default:throw this.astErrorOutput(`Unhandled switch discriminant type "${i}"`,e)}if(1===n.length&&!n[0].test)return void this.vEmitSwitchConsequent(n[0].consequent);const{groups:o,defaultConsequent:u}=this.collectSwitchGroups(n),l=e=>{if(e===o.length)return void(u&&this.vEmitSwitchConsequent(u));const{tests:t,consequent:n}=o[e];for(let e=0;e0&&r.i32Or();this.enterIf(),this.vEmitSwitchConsequent(n),(e+10&&r.v128Or();r.localSet(p),this.vRecomputeCur(h),r.localGet(this.vCur).localGet(p).v128And().localGet(c).v128Andnot().localSet(this.vCur),r.localGet(c).localGet(p).v128Or().localSet(c),r.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(n),this.exit()}l&&(this.vRecomputeCur(h),r.localGet(this.vCur).localGet(c).v128Andnot().localSet(this.vCur),r.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(l),this.exit()),this.vMaskDepth--,this.vRecomputeCur(h)}vEmitSwitchTest(e,t){const n=this.getType(e);t?"Number"===n||"Float"===n?this.vCastValueToInteger(e):"LiteralInteger"===n?this.vCastLiteralToInteger(e):this.vCoerce(this.vexpr(e),"vi32"):"LiteralInteger"===n?this.vCastLiteralToFloat(e):"Integer"===n?this.vCastValueToFloat(e):this.vCoerce(this.vexpr(e),"vf32")}vEmitSwitchConsequent(e){const t=this.collectSwitchCaseStatements(e),n=this.vTerminated;this.vTerminated=!1;for(let e=0;e{const n=this.getType(t);switch(s){case"Number":case"Float":"Integer"===n?this.vCastValueToFloat(t):"LiteralInteger"===n?this.vCastLiteralToFloat(t):this.vCoerce(this.vexpr(t),"vf32");break;case"Integer":"Number"===n||"Float"===n?this.vCastValueToInteger(t):"LiteralInteger"===n?this.vCastLiteralToInteger(t):this.vCoerce(this.vexpr(t),"vi32");break;case"Boolean":this.vexprMask(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${s}`,e)}},a="Integer"===s?"vi32":"Boolean"===s?"vbool":"vf32";if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf("v128"),i(e.consequent),t.else_(),i(e.alternate),this.exit(),a;const o=t.addLocal("v128");this.vexprMask(e.test),t.localSet(o);const u=t.addLocal("v128");t.localGet(this.vCur).localSet(u);const l=t.addLocal("v128"),h=t.addLocal("v128");return t.localGet(u).localGet(o).v128And().localSet(this.vCur),this.vMaskDepth++,i(e.consequent),t.localSet(l),t.localGet(u).localGet(o).v128Andnot().localSet(this.vCur),i(e.alternate),t.localSet(h),this.vMaskDepth--,t.localGet(u).localSet(this.vCur),t.localGet(l).localGet(h).localGet(o).v128Bitselect(),a}vTernaryStatement(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementExpression(e.consequent),t.else_(),this.vstatementExpression(e.alternate),void this.exit();const n=t.addLocal("v128");this.vexprMask(e.test),t.localSet(n);const r=t.addLocal("v128");t.localGet(this.vCur).localSet(r),t.localGet(r).localGet(n).v128And().localSet(this.vCur),this.vMaskDepth++,this.vstatementExpression(e.consequent),t.localGet(r).localGet(n).v128Andnot().localSet(this.vCur),this.vstatementExpression(e.alternate),this.vMaskDepth--,t.localGet(r).localSet(this.vCur)}vexprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const n=this.isAstMathFunction(e);if(t=n||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);return n?this.vMathCall(t,e):this.vUserCall(t,e)}vUserCall(e,t){const n=this.em,r=this.assembler.helperInfo||{readsThread:!1,usesRandom:!1},s=this.assembler.globals,i=this.getType(t),a=this.lookupFunctionArgumentTypes(e)||[],o=[];for(let r=0;r0&&n.i32Const(t).i32Add(),n.globalSet(s.threadX)),r.usesRandom&&n.localGet(c).i32x4ExtractLane(t).globalSet(s.pcgState);for(const e of o)n.localGet(e.index),"vi32"===e.wtype?n.i32x4ExtractLane(t):n.f32x4ExtractLane(t);n.call(this.mangleFunctionName(e)),"void"!==u&&n.localSet(l),r.usesRandom&&n.localGet(c).globalGet(s.pcgState).i32x4ReplaceLane(t).localSet(c),"void"!==u&&(0===t?(n.localGet(l),"i32"===u?n.i32x4Splat():n.f32x4Splat(),n.localSet(h)):(n.localGet(h).localGet(l),"i32"===u?n.i32x4ReplaceLane(t):n.f32x4ReplaceLane(t),n.localSet(h)))}return r.readsThread&&n.localGet(this._vBaseX).globalSet(s.threadX),r.usesRandom&&(n.localGet(c).globalGet(s.pcgStateV),this.vMaskDepth>0?n.localGet(this.vCur):n.v128ConstI32x4(-1,-1,-1,-1),n.v128Bitselect().globalSet(s.pcgStateV)),"void"===u?"void":(n.localGet(h),"i32"===u?"vi32":"vf32")}vMathCall(e,t){const n=this.em;if("random"===e)return this.usesRandom=!0,this.vMaskDepth>0?n.localGet(this.vCur):n.v128ConstI32x4(-1,-1,-1,-1),n.call("pcg_random_v"),"vf32";const r=e=>{switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}},s=v[e];if(s)return r(t.arguments[0]),n[s](),"vf32";switch(e){case"round":return r(t.arguments[0]),n.v128ConstF32x4(.5,.5,.5,.5).f32x4Add().f32x4Floor(),"vf32";case"fround":return r(t.arguments[0]),"vf32";case"min":case"max":{const s="min"===e?"f32x4Min":"f32x4Max";r(t.arguments[0]);for(let e=1;e{n.localGet(e.indices[t]),"vec"===e.kind&&n.f32x4Splat()};if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return r(t.value),"vf32"}const s=n.addLocal("v128");this.vEmitIndex(t),n.localSet(s);const i=n.addLocal("v128");r(0),n.localSet(i);for(let t=1;tthis.isThreadDependent(e));switch(e.type){case"MemberExpression":{const t=this.getVariableSignature(e);if("this.thread.value"===t||"value.thread.value"===t)return"x"===e.property.name;break}case"CallExpression":if(this.isAstMathFunction(e)){if("random"===e.callee.property.name)return!0;break}return!0;case"Identifier":return!!this.taintedLocals&&this.taintedLocals.has(e.name);case"ThisExpression":return!1}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const n=e[t];if(n&&"object"==typeof n&&this.isThreadDependent(n))return!0}return!1}recordUniformity(e,t){this._analysisPass&&this.uniformity.push({kind:e,threadDependent:!t||this.isThreadDependent(t)})}}}}),ut=e((e,t)=>{let r=null;try{r=n()}catch(e){}const s="function"==typeof Worker;const i="\nvar entries = {};\nvar pipelines = {};\nfunction handleMessage(message, post) {\n if (message.type === 'setup') {\n var imports = { env: { memory: message.memory } };\n for (var i = 0; i < message.mathImports.length; i++) {\n imports.env['math_' + message.mathImports[i]] = Math[message.mathImports[i]];\n }\n var instance = new WebAssembly.Instance(message.module, imports);\n entries[message.id] = {\n run: instance.exports.run,\n runSimd: instance.exports.run_simd || null,\n sizeX: message.sizeX\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'pipelineSetup') {\n var instances = [];\n for (var i = 0; i < message.modules.length; i++) {\n var imports = { env: { memory: message.memory } };\n var math = message.moduleMathImports[i];\n for (var j = 0; j < math.length; j++) {\n imports.env['math_' + math[j]] = Math[math[j]];\n }\n instances.push(new WebAssembly.Instance(message.modules[i], imports));\n }\n var steps = [];\n for (var i = 0; i < message.steps.length; i++) {\n var exported = instances[message.steps[i].module].exports;\n steps.push({\n run: exported.run,\n runSimd: exported.run_simd || null,\n sizeX: message.steps[i].sizeX\n });\n }\n pipelines[message.id] = {\n steps: steps,\n i32: new Int32Array(message.memory.buffer),\n countIndex: message.countIndex,\n genIndex: message.genIndex,\n abortIndex: message.abortIndex\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'release') {\n delete entries[message.id];\n delete pipelines[message.id];\n } else if (message.type === 'run') {\n var entry = entries[message.id];\n var start = message.start;\n var end = message.end;\n var seed = message.seed;\n if (entry.runSimd && (entry.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) entry.runSimd(start, quadEnd, seed);\n if (quadEnd < end) entry.run(quadEnd, end, seed);\n } else {\n entry.run(start, end, seed);\n }\n post({ type: 'done', taskId: message.taskId });\n } else if (message.type === 'pipelineRun') {\n var pipeline = pipelines[message.id];\n var i32 = pipeline.i32;\n var gen = message.baseGen;\n var aborted = false;\n for (var s = 0; s < pipeline.steps.length && !aborted; s++) {\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n var step = pipeline.steps[s];\n var start = message.ranges[s * 2];\n var end = message.ranges[s * 2 + 1];\n var seed = message.seeds[s];\n if (end > start) {\n if (step.runSimd && (step.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) step.runSimd(start, quadEnd, seed);\n if (quadEnd < end) step.run(quadEnd, end, seed);\n } else {\n step.run(start, end, seed);\n }\n }\n gen++;\n if (Atomics.add(i32, pipeline.countIndex, 1) + 1 === message.workerCount) {\n Atomics.store(i32, pipeline.countIndex, 0);\n Atomics.store(i32, pipeline.genIndex, gen);\n Atomics.notify(i32, pipeline.genIndex);\n } else {\n for (;;) {\n if (Atomics.load(i32, pipeline.genIndex) >= gen) break;\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n Atomics.wait(i32, pipeline.genIndex, gen - 1, 100);\n }\n }\n }\n post({ type: 'done', taskId: message.taskId, aborted: aborted });\n }\n}\nif (typeof self !== 'undefined' && typeof postMessage === 'function') {\n self.onmessage = function(event) {\n handleMessage(event.data, function(message) { postMessage(message); });\n };\n} else {\n var parentPort = require('worker_threads').parentPort;\n parentPort.on('message', function(message) {\n handleMessage(message, function(reply) { parentPort.postMessage(reply); });\n });\n}\n";t.exports={WebAssemblyWorkerPool:class{constructor(e){this.size=e||function(){if("undefined"!=typeof navigator&&navigator.hardwareConcurrency)return navigator.hardwareConcurrency;if(r&&"function"==typeof r.cpus){const e=r.cpus().length;if(e)return e}return 4}(),this.workers=[],this.destroyed=!1,this.dispatchCount=0,this.lastDispatch=null,this._taskId=0}get liveWorkerCount(){let e=0;for(const t of this.workers)t.dead||e++;return e}_spawn(){const e={handle:null,dead:!1,state:{setup:new Set,settingUp:new Map,pending:new Map},fail:null,die:null},t=e.state;e.fail=e=>{for(const n of t.settingUp.values())n.reject(e);t.settingUp.clear();for(const n of t.pending.values())n.reject(e);t.pending.clear()},e.die=t=>{if(!e.dead&&(e.dead=!0,e.fail(t),e.handle&&"function"==typeof e.handle.terminate))try{e.handle.terminate()}catch(e){}};const r=n=>{if("ready"===n.type){const r=t.settingUp.get(n.id);r&&(t.settingUp.delete(n.id),t.setup.add(n.id),this._updateRef(e),r.resolve())}else if("done"===n.type){const r=t.pending.get(n.taskId);r&&(t.pending.delete(n.taskId),this._updateRef(e),r.resolve())}};let a;if(s){const t=URL.createObjectURL(new Blob([i],{type:"text/javascript"}));a=new Worker(t),URL.revokeObjectURL(t),a.onmessage=e=>r(e.data),a.onerror=t=>e.die(new Error(t.message||"WebAssembly worker error"))}else{const{Worker:t}=n();a=new t(i,{eval:!0}),a.on("message",r),a.on("error",t=>e.die(t)),a.on("exit",t=>{e.die(new Error(`WebAssembly worker exited with code ${t}`))}),a.unref()}return e.handle=a,e}_worker(e){for(;this.workers.length<=e;)this.workers.push(this._spawn());return this.workers[e].dead&&(this.workers[e]=this._spawn()),this.workers[e]}_updateRef(e){!e.dead&&e.handle&&"function"==typeof e.handle.ref&&(e.state.settingUp.size+e.state.pending.size>0?e.handle.ref():e.handle.unref())}_ensureSetup(e,t){if(e.state.setup.has(t.id))return Promise.resolve();let n=e.state.settingUp.get(t.id);return n||(n={},n.promise=new Promise((e,t)=>{n.resolve=e,n.reject=t}),e.state.settingUp.set(t.id,n),this._updateRef(e),e.handle.postMessage(t.pipeline?{type:"pipelineSetup",id:t.id,memory:t.memory,modules:t.modules,moduleMathImports:t.moduleMathImports,steps:t.steps,countIndex:t.countIndex,genIndex:t.genIndex,abortIndex:t.abortIndex}:{type:"setup",id:t.id,module:t.module,memory:t.memory,mathImports:t.mathImports,sizeX:t.sizeX})),n.promise}dispatch(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:t.length,ranges:t.map(e=>[e.start,e.end])};const n=t.map((t,n)=>{const r=this._worker(n);return this._ensureSetup(r,e).then(()=>new Promise((n,s)=>{if(r.dead)return void s(new Error("WebAssembly worker died before the task could run"));const i=++this._taskId;r.state.pending.set(i,{resolve:n,reject:s}),this._updateRef(r),r.handle.postMessage({type:"run",id:e.id,taskId:i,start:t.start,end:t.end,seed:t.seed})}))});return Promise.all(n).then(()=>{})}dispatchPipeline(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:e.workerCount,ranges:e.workerRanges.map(e=>e.slice())};const n=[];for(let r=0;rnew Promise((n,i)=>{if(s.dead)return void i(new Error("WebAssembly worker died before the task could run"));const a=++this._taskId;s.state.pending.set(a,{resolve:n,reject:i}),this._updateRef(s),s.handle.postMessage({type:"pipelineRun",id:e.id,taskId:a,ranges:e.workerRanges[r],seeds:t.seeds,baseGen:t.baseGen,workerCount:e.workerCount})})))}return Promise.all(n).then(()=>{})}release(e){if(!this.destroyed)for(const t of this.workers){if(t.dead)continue;t.state.setup.delete(e);const n=t.state.settingUp.get(e);n&&(t.state.settingUp.delete(e),n.reject(new Error("WebAssembly kernel entry released during setup")),this._updateRef(t)),t.handle.postMessage({type:"release",id:e})}}destroy(){if(this.destroyed)return;this.destroyed=!0;const e=new Error("WebAssembly worker pool has been destroyed");for(const t of this.workers)t.dead=!0,t.fail(e),t.handle.terminate();this.workers=[]}}}}),lt=e((e,t)=>{const{Kernel:n}=a(),{FunctionBuilder:s}=u(),{WebAssemblyFunctionNode:o}=ot(),{WasmModuleBuilder:l}=at(),{WebAssemblyWorkerPool:h}=ut(),{utils:c}=i(),{Input:p}=r(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0});let f=null,m=null,g=1;t.exports={WebAssemblyKernel:class e extends n{static get isSupported(){return"object"==typeof WebAssembly&&null!==WebAssembly&&WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0]))}static get isSIMDSupported(){if(null===f)try{const e=new l;e.addFunction("t",{params:[],results:[]}).v128ConstI32x4(0,0,0,0).drop(),f=WebAssembly.validate(e.toBytes())}catch(e){f=!1}return f}static get isThreadsSupported(){if(null===m)try{if("undefined"==typeof SharedArrayBuffer)m=!1;else{const e=new l;e.addMemoryImport(1,1,!0);const t=new WebAssembly.Memory({initial:1,maximum:1,shared:!0});new WebAssembly.Instance(new WebAssembly.Module(e.toBytes()),{env:{memory:t}}),m=!0}}catch(e){m=!1}return m}static isContextMatch(e){return!1}static getFeatures(){return d}static get features(){return d}static get mode(){return"webasm"}static getSignature(e,t){return"webasm"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static dispatchSpans(e,t,n,r,s){if(!t||0===n)return e(0,n,s),"scalar";if(!(3&r))return t(0,n,s),"simd";const i=-4&r,a=n/r;for(let n=0;n0&&t(a,a+i,s),e(a+i,a+r,s)}return i>0?"simd+scalar-tail":"scalar"}static nativeFunctionArguments(){throw new Error("WebAssembly backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebAssembly backend does not yet support native functions")}static combineKernels(){throw new Error("WebAssembly backend does not yet support combineKernels")}constructor(e,t){super(e,t),this.poolSize=null,this.mergeSettings(e.settings||t),null===this.precision&&(this.precision="single"),this.threadDim=null,this.componentCount=1,this.moduleCacheLimit=8,this.functionBuilder=null,this.tracedFunctions=null,this.usesRandom=!1,this.usedMathImports=null,this._moduleCache=new Map,this._active=null,this._lastRunPath=null,this._pool=null,this._threadedTail=Promise.resolve(),this._threadedBusy=0,this._threadedEpoch=0}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built&&!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");return this.output=t,this}toString(){throw new Error("WebAssembly backend does not yet support toString")}build(){if(this.built)return;if(this.gpu&&this.gpu.kernels&&-1===this.gpu.kernels.indexOf(this)&&this.gpu.kernels.push(this),this.graphical)return this.requestFallback(arguments,"graphical mode is not supported on the webasm backend");if(this.subKernels&&this.subKernels.length>0)return this.requestFallback(arguments,"kernel maps are not supported on the webasm backend");this.setupConstants(),this.setupArguments(arguments);for(let e=0;e{this.translateSource()?(t=!1,this.buildSignature(arguments),this._instantiate(this._entryKey(arguments),arguments)):t=!0}),t)return this.requestFallback(arguments,`return type ${this.returnType} is not supported on the webasm backend`);this.built=!0}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(c.getDimensions(e[0]))}this.checkOutput()}translateSource(){const e=this.functionBuilder=s.fromKernel(this,o);switch(this.tracedFunctions=e.traceFunctionCalls("kernel",[]),this.returnType||(this.returnType=e.getKernelResultType()),this.returnType){case"Number":case"Float":case"Integer":case"LiteralInteger":this.componentCount=1;break;case"Array(2)":this.componentCount=2;break;case"Array(3)":this.componentCount=3;break;case"Array(4)":this.componentCount=4;break;default:return!1}this.usesRandom=!1,this.usedMathImports=new Set;for(const t of this.tracedFunctions){const n=e.functionMap[t];if(n){n.usesRandom&&(this.usesRandom=!0);for(const e of n.usedMathImports)this.usedMathImports.add(e)}}return!0}computeLayout(e){const t=e=>16*Math.ceil(e/16);let n=0;const r={},s={};for(let i=0;i=4096}_entryKey(e){return this._computeSizeSignature(e)+(this._threadable()?"|shared":"")}_assembleModule(t,n,r){const s=new l,i=t.totalBytes||t.outputOffset+n*this.componentCount*4,a=Math.ceil(i/65536)+16,o=Math.max(a,4096);s.addMemoryImport(a,o,r);const u=Array.from(this.usedMathImports).sort();for(const e of u){const t="pow"===e||"atan2"===e?["f32","f32"]:["f32"];s.addFuncImport("math_"+e,t,["f32"])}const h={threadX:s.addGlobal("i32",!0,0),threadY:s.addGlobal("i32",!0,0),threadZ:s.addGlobal("i32",!0,0),dataIndex:s.addGlobal("i32",!0,0)};this.usesRandom&&(h.pcgState=s.addGlobal("i32",!0,0),this._emitPcgRandom(s,h.pcgState));const c={module:s,layout:t,globals:h};for(let e=this.tracedFunctions.length-1;e>=0;e--){const t=this.tracedFunctions[e];if("kernel"===t)continue;const n=this.functionBuilder.functionMap[t];n&&(n.output=this.output,n.emitFunction(c))}this.functionBuilder.functionMap.kernel.output=this.output,this.functionBuilder.functionMap.kernel.emitFunction(c);const[p,d]=this.threadDim,f=s.addFunction("run",{params:["i32","i32","i32"],locals:["i32"]});if(f.localGet(0).localSet(3),1===this.output.length?(f.i32Const(0).globalSet(h.threadY),f.i32Const(0).globalSet(h.threadZ)):2===this.output.length&&f.i32Const(0).globalSet(h.threadZ),f.block(),f.localGet(3).localGet(1).i32GeS().brIf(0),f.loop(),f.localGet(3).globalSet(h.dataIndex),1===this.output.length?f.localGet(3).globalSet(h.threadX):2===this.output.length?(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().globalSet(h.threadY)):(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().i32Const(d).i32RemU().globalSet(h.threadY),f.localGet(3).i32Const(p*d).i32DivU().globalSet(h.threadZ)),this.usesRandom&&f.localGet(2).localGet(3).i32Const(-1640531527).i32Mul().i32Add().i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(h.pcgState),f.call("kernel"),f.localGet(3).i32Const(1).i32Add().localSet(3),f.localGet(3).localGet(1).i32LtS().brIf(0),f.end(),f.end(),s.exportFunction("run"),e.isSIMDSupported){this.usesRandom&&(h.pcgStateV=s.addGlobal("v128",!0,0),this._emitPcgRandomVector(s,h.pcgStateV));let e=null;for(const t of this.tracedFunctions){if("kernel"===t)continue;const n=this.functionBuilder.functionMap[t];n&&(e||(e={readsThread:!1,usesRandom:!1}),n.readsThread&&(e.readsThread=!0),n.usesRandom&&(e.usesRandom=!0))}c.helperInfo=e,this.functionBuilder.functionMap.kernel.emitVectorFunction(c),this._emitRunSimd(s,h),s.exportFunction("run_simd")}return{bytes:s.toBytes(),initial:a,maximum:o}}_emitRunSimd(e,t){const[n,r]=this.threadDim,s=e.addFunction("run_simd",{params:["i32","i32","i32"],locals:["i32"]});s.localGet(0).localSet(3),1===this.output.length?(s.i32Const(0).globalSet(t.threadY),s.i32Const(0).globalSet(t.threadZ)):2===this.output.length&&s.i32Const(0).globalSet(t.threadZ),s.block(),s.localGet(3).localGet(1).i32GeS().brIf(0),s.loop(),s.localGet(3).globalSet(t.dataIndex),1===this.output.length?s.localGet(3).globalSet(t.threadX):2===this.output.length?(s.localGet(3).i32Const(n).i32RemU().globalSet(t.threadX),s.localGet(3).i32Const(n).i32DivU().globalSet(t.threadY)):(s.localGet(3).i32Const(n).i32RemU().globalSet(t.threadX),s.localGet(3).i32Const(n).i32DivU().i32Const(r).i32RemU().globalSet(t.threadY),s.localGet(3).i32Const(n*r).i32DivU().globalSet(t.threadZ)),this.usesRandom&&(s.localGet(3).i32x4Splat().v128ConstI32x4(0,1,2,3).i32x4Add(),s.v128ConstI32x4(-1640531527,-1640531527,-1640531527,-1640531527).i32x4Mul(),s.localGet(2).i32x4Splat().i32x4Add(),s.v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul(),s.v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add(),s.globalSet(t.pcgStateV)),s.call("kernel_simd"),s.localGet(3).i32Const(4).i32Add().localSet(3),s.localGet(3).localGet(1).i32LtS().brIf(0),s.end(),s.end()}_emitPcgRandomVector(e,t){const n=e.addFunction("pcg_random_v",{params:["v128"],results:["v128"]}),r=n.addLocal("v128"),s=n.addLocal("i32");n.globalGet(t).v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul().v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add().globalGet(t).localGet(0).v128Bitselect().globalSet(t),n.globalGet(t).localSet(r),n.localGet(r).i32x4ExtractLane(0).localSet(s),n.localGet(s).localGet(s).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4Splat();for(let e=1;e<4;e++)n.localGet(r).i32x4ExtractLane(e).localSet(s),n.localGet(s).localGet(s).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4ReplaceLane(e);n.localGet(r).v128Xor(),n.v128ConstI32x4(277803737,277803737,277803737,277803737).i32x4Mul();const i=n.addLocal("v128");n.localTee(i),n.i32Const(22).i32x4ShrU().localGet(i).v128Xor(),n.i32Const(8).i32x4ShrU(),n.f32x4ConvertI32x4U(),n.v128ConstF32x4(16777216,16777216,16777216,16777216).f32x4Div()}_emitPcgRandom(e,t){const n=e.addFunction("pcg_random",{params:[],results:["f32"]}),r=n.addLocal("i32");n.globalGet(t).i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(t),n.globalGet(t).globalGet(t).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().globalGet(t).i32Xor().i32Const(277803737).i32Mul().localTee(r),n.i32Const(22).i32ShrU().localGet(r).i32Xor().i32Const(8).i32ShrU().f32ConvertI32U().f32Const(16777216).f32Div()}_releaseEntry(e){const t=()=>{e.instance=null,e.module=null,e.memory=null,e.run=null,e.runSimd=null,e.f32=null,e.i32=null,e.bytes=null};if(e.shared&&this._pool){const n=this._pool;this._threadedTail.then(()=>{n.release(e.id),t()},t)}else t()}_instantiate(e,t){let n=this._moduleCache.get(e);if(n&&(this._moduleCache.delete(e),this._moduleCache.set(e,n)),!n){const r=this._threadable(),s=this.computeLayout(t),[i,a,o]=this.threadDim,u=i*a*o,{bytes:l,initial:h,maximum:d}=this._assembleModule(s,u,r);if(!WebAssembly.validate(l))throw new Error("WebAssembly backend: generated module failed validation (internal error)");const f=r?new WebAssembly.Memory({initial:h,maximum:d,shared:!0}):new WebAssembly.Memory({initial:h,maximum:d}),m={env:{memory:f}};for(const e of this.usedMathImports)m.env["math_"+e]=Math[e];const y=new WebAssembly.Module(l),x=new WebAssembly.Instance(y,m);n={id:g++,sizeSignature:e,shared:r,layout:s,cells:u,bytes:l,module:y,memory:f,mathImports:Array.from(this.usedMathImports).sort(),sizeX:i,instance:x,run:x.exports.run,runSimd:x.exports.run_simd||null,f32:new Float32Array(f.buffer),i32:new Int32Array(f.buffer)};for(const e in s.constantArrays){const t=s.constantArrays[e],r=this.constants[e];c.flattenTo(r instanceof p?r.value:r,n.f32.subarray(t.offset/4,t.offset/4+t.flatLength))}for(this._moduleCache.set(e,n);this._moduleCache.size>Math.max(this.moduleCacheLimit,1);){const e=this._moduleCache.keys().next().value,t=this._moduleCache.get(e);this._moduleCache.delete(e),this._releaseEntry(t)}}this._active=n}checkArgumentTypes(e){if(super.checkArgumentTypes(e),!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let n=0;n>>0:4294967296*Math.random()>>>0),l|=0,this._lastRunPath=e.dispatchSpans(o,u,s,t[0],l);const h=r.outputOffset/4,d=i.slice(h,h+s*this.componentCount);return this._shapeOutput(d,Array.from(this.output),this.componentCount)}_runThreaded(e){const t=this._active,{layout:n,cells:r}=t,s=0===this._threadedBusy;let i=null,a=null;if(s){for(const r in n.arrays){const s=n.arrays[r],i=e[s.index];c.flattenTo(i instanceof p?i.value:i,t.f32.subarray(s.offset/4,s.offset/4+s.flatLength))}for(const r in n.scalars){const s=n.scalars[r],i=e[s.index];"Integer"===s.type?t.i32[s.offset/4]=0|i:"Boolean"===s.type?t.i32[s.offset/4]=i?1:0:t.f32[s.offset/4]=i}}else{i=[];for(const t in n.arrays){const r=n.arrays[t],s=e[r.index],a=new Float32Array(r.flatLength);c.flattenTo(s instanceof p?s.value:s,a),i.push({record:r,flat:a})}a=[];for(const t in n.scalars){const r=n.scalars[t];a.push({record:r,value:e[r.index]})}}let o=0;this.usesRandom&&(o=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0),o|=0,this._pool||(this._pool=new h(this.poolSize||void 0));const u=this._pool,l=this.componentCount,d=Array.from(this.output);this._threadedBusy++;const f=this._threadedTail.then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");if(i){for(let e=0;e=r)break;h.push({start:n,end:t===e-1?r:Math.min(n+s,r),seed:o})}return this._lastRunPath="threaded",u.dispatch(t,h).then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");const e=n.outputOffset/4,s=t.f32.slice(e,e+r*l);return this._shapeOutput(s,d,l)})}),m=this._threadedEpoch,g=()=>{this._threadedEpoch===m&&this._threadedBusy--};return this._threadedTail=f.then(g,g),f}_shapeOutput(e,t,n){const[r,s,i]=[t[0],t[1]||1,t[2]||1];if(1===n)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,r);case 2:return c.erectMemoryOptimized2DFloat(e,r,s);default:return c.erectMemoryOptimized3DFloat(e,r,s,i)}const a=n,o=t=>{const n=new Array(r);for(let s=0;s{const{utils:n}=i(),{Input:s}=r(),{WebAssemblyKernel:a}=lt(),{WebAssemblyWorkerPool:o}=ut(),u=["Array","Input","Number","Float","Integer","Boolean"];let l=1;var h=class extends Error{constructor(e,t){super(e),this.isFusionFallback=!0,this.recompilable=Boolean(t)}};function c(e){return e&&"function"==typeof e.toArray?e.toArray():e}function p(e){const t=e instanceof s?Array.from(e.size):Array.from(n.getDimensions(e));for(;t.length<3;)t.push(1);return t}function d(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}t.exports={WebAssemblyPipelineExecutor:class e{static compile(t,n,r){for(let e=0;en.getVariableType(e,h)).join(",");let d=r.get(p);if(!d){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(o.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=o.clone.kernel;this._prepareKernel(e,l),d={id:r.size,kernel:e,constantRegions:null},r.set(p,d)}u[s]=d,c[s]=l}for(let e=0;e{const t=p;return p=(e=>16*Math.ceil(e/16))(p+e),t};let f=0,m=-1;if(!this.pipeline._threadsDisabled&&a.isThreadsSupported){let e=0;for(let n=0;ne&&(e=s)}const n=new o;f=Math.min(n.size,Math.ceil(e/4096)),f>1?(this.threaded=!0,this.kind="fused-threaded",this.pool=n,m=d(12)):n.destroy()}const g=new Map,y=new Map,x=new Map,b=[],v=[],S=[],T=new Array(t.steps.length);for(let e=0;e${i}`;let l=I.get(o);if(!l){const a={arrays:s.arrays,scalars:s.scalars,constantArrays:n.constantRegions,outputOffset:i,totalBytes:E},u=w[t.steps[e].outputBuffer].cells,h=r._assembleModule(a,u,this.threaded);null===this.memory&&(this.memory=this.threaded?new WebAssembly.Memory({initial:h.initial,maximum:h.maximum,shared:!0}):new WebAssembly.Memory({initial:h.initial,maximum:h.maximum}),this.f32=new Float32Array(this.memory.buffer),this.i32=new Int32Array(this.memory.buffer));const c={env:{memory:this.memory}};for(const e of r.usedMathImports)c.env["math_"+e]=Math[e];const p=new WebAssembly.Module(h.bytes),d=new WebAssembly.Instance(p,c);l={run:d.exports.run,runSimd:d.exports.run_simd||null,moduleIndex:k.length},k.push(p),L.push(Array.from(r.usedMathImports).sort()),I.set(o,l)}_[e]={run:l.run,runSimd:l.runSimd,moduleIndex:l.moduleIndex,cells:w[t.steps[e].outputBuffer].cells,sizeX:r.threadDim[0],usesRandom:r.usesRandom,randomSeed:r.randomSeed}}if(this.threaded){const e=[];for(let n=0;n=t?(r[2*e]=0,r[2*e+1]=0):(r[2*e]=i,r[2*e+1]=n===f-1?t:Math.min(i+s,t))}e.push(r)}this._entry={id:"pipeline:"+l++,pipeline:!0,memory:this.memory,modules:k,moduleMathImports:L,steps:_.map(e=>({module:e.moduleIndex,sizeX:e.sizeX})),countIndex:m/4,genIndex:m/4+1,abortIndex:m/4+2,workerCount:f,workerRanges:e}}for(let e=0;e{const n=e.binding;if("step"===n.source){const e=n.step,r=w[t.steps[e].outputBuffer],s=u[e].kernel;return{kind:"step",base:r.offset/4,count:r.cells*s.componentCount,output:t.steps[e].output,componentCount:s.componentCount,kernel:s}}return"pipelineArg"===n.source?{kind:"arg",index:n.index}:{kind:"literal",value:n.value}}),this._stepRuns=_,this._argArrayRegions=g,this._argScalarSlots=y,this._scratch=null}_representativeArgs(e,t){const n=new Array(e.argBindings.length);for(let r=0;r>>0:4294967296*Math.random()>>>0):0}_executeThreaded(e){const t=this._entry,n=this.i32,r=this._stepRuns.map(e=>this._drawSeed(e));this._lastRunAborted&&(Atomics.store(n,t.countIndex,0),Atomics.store(n,t.abortIndex,0),this._lastRunAborted=!1,this._abortError=null);const s=Atomics.load(n,t.genIndex),i=s+this._stepRuns.length;return this.pool.dispatchPipeline(t,{baseGen:s,seeds:r}).then(null,e=>this._abort(e)),this._waitForGeneration(i).then(()=>this._readResults(e))}_waitForGeneration(e){const t=this.i32,n=this._entry.genIndex,r="function"==typeof Atomics.waitAsync?Atomics.waitAsync:null;return new Promise((s,i)=>{const a="function"==typeof setInterval?setInterval(()=>{},200):null,o=(e,t)=>{null!==a&&clearInterval(a),e(t)},u=this._entry.countIndex;let l=Atomics.load(t,n),h=Atomics.load(t,u),c=Date.now();const p=()=>{if(this._abortError)return void o(i,this._abortError);const a=Atomics.load(t,n);if(a>=e)return void o(s);const d=Atomics.load(t,u);if(a!==l||d!==h)l=a,h=d,c=Date.now();else if(Date.now()-c>=this.sanityTimeoutMs){const t=new Error(`pipeline threaded barrier stalled at generation ${a} of ${e} for ${this.sanityTimeoutMs}ms`);return this._abort(t),void o(i,t)}if(r){const e=Math.max(1,Math.min(200,this.sanityTimeoutMs)),s=r(t,n,a,e);s.async?s.value.then(p):Promise.resolve().then(p)}else setTimeout(p,1)};p()})}_abort(e){if(!this._abortError&&(this._abortError=e||new Error("pipeline threaded run aborted"),this._lastRunAborted=!0,this.i32&&this._entry&&(Atomics.store(this.i32,this._entry.abortIndex,1),Atomics.notify(this.i32,this._entry.genIndex)),this.pool&&this.pool.workers))for(const e of this.pool.workers)!e.dead&&e.state.pending.size>0&&e.die(this._abortError)}abortRuns(e){this.threaded&&this._abort(e)}_readResults(e){const t=this.f32,n=this.plan.results,r=new Array(this._resultReads.length);for(let n=0;n{const{utils:n}=i(),{Input:s}=r(),{FusionFallback:a}=ht();function o(e){return e&&"function"==typeof e.toArray?e.toArray():e}function u(e,t,n){const r=e.limits,s=Math.min(r.maxStorageBufferBindingSize,r.maxBufferSize);if(t>s)throw new a(`${n} needs ${t} bytes but this device allows ${s} per storage buffer`)}function l(e){const t=e instanceof s?Array.from(e.size):Array.from(n.getDimensions(e));for(;t.length<3;)t.push(1);return t}function h(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}function c(e){return Boolean(e)&&"object"==typeof e&&!(e instanceof s)&&("function"==typeof e.toArray||"function"==typeof e.delete)}t.exports={WebGPUPipelineExecutor:class e{static async compile(t,n,r){for(let e=0;en.getVariableType(e,h)).join(",");let p=r.get(c);if(!p){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(u.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=u.clone.kernel;await this._prepareKernel(e,l),p={id:r.size,kernel:e},r.set(c,p)}o[s]=p}this._scratch=null;for(let e=0;e{const n=e.output;let r=1;for(let e=0;e{let t=f.get(e);return void 0===t&&(t=f.size,f.set(e,t)),t},g=new Map;this._passes=new Array(t.steps.length);for(let r=0;r{const t=i.argBindings[e.index];return"literal"===t.source?"l"+t.value:"a"+t.index}).join(","),S=null!==f.randomSeedOffset&&null===d.randomSeed,T=c.id+":"+y.map(m).join(",")+">"+m(b)+":"+v+(S?"#"+r:"");let A=g.get(T);if(!A){const e=new ArrayBuffer(f.byteLength),t=new Uint32Array(e),n=new Int32Array(e),r=new Float32Array(e),s=d._computeDispatch(d.threadDim);t[0]=d.threadDim[0],t[1]=d.threadDim[1],t[2]=d.threadDim[2],t[3]=s.dispatchWidth;for(let e=0;e>>0);const u=h.createBuffer({size:f.byteLength,usage:72}),l=o.length>0||S;l||p.writeBuffer(u,0,e);const c=[{binding:0,resource:{buffer:u}}];for(let e=0;e{const n=e.binding;if("step"===n.source){const e=t.steps[n.step],r=this._planBuffers[e.outputBuffer],s=o[n.step].kernel,i=r.cells*s.componentCount*4,a={kind:"step",buffer:r.buffer,offset:y,byteLength:i,output:e.output,componentCount:s.componentCount,kernel:s};return y+=function(e){return 16*Math.ceil(e/16)}(i),a}return"pipelineArg"===n.source?{kind:"arg",index:n.index}:{kind:"literal",value:n.value}}),y>0&&(this._staging=h.createBuffer({size:y,usage:9}))}_representativeArgs(e,t){const n=new Array(e.argBindings.length);for(let r=0;r>>0),r.writeBuffer(n.paramsBuffer,0,n.mirror)}}const i=t.createCommandEncoder();for(let e=0;e{const t=this._staging.getMappedRange(),n=this._shapeResults(e,t);return this._staging.unmap(),n}):Promise.resolve(this._shapeResults(e,null))}_shapeResults(e,t){const n=this.plan.results,r=new Array(this._resultReads.length);for(let n=0;n{const{Input:n}=r(),{utils:s}=i(),a="pipeline intermediate results cannot be read during orchestration",o="a pipeline must return a handle, or an Array or plain object of handles",u="pipeline has been destroyed",l="the orchestration function must be synchronous; async functions and generators cannot be traced",h="this handle belongs to a different trace; handles do not survive re-trace or cross pipelines";var c=class{};let p=null;var d=class{constructor(e){this.gpu=e,this.steps=[],this.kernels=[],this.kernelIndexes=new Map,this.handleMeta=new WeakMap,this.held=[]}createHandle(e){const t=Object.freeze(new c),n=new Proxy(t,{get(e,t){if(t===Symbol.toPrimitive||"valueOf"===t||"toString"===t)return()=>{throw new Error("pipeline intermediate results cannot be used in arithmetic or conditions during orchestration")};throw new Error(a)},set(){throw new Error(a)},ownKeys(){throw new Error(a)},has(){throw new Error(a)},getOwnPropertyDescriptor(){throw new Error(a)}});return this.handleMeta.set(n,e),n}recordKernelCall(e,t){const n=e.kernel;if(n.gpu!==this.gpu)throw new Error("pipelines can only call kernels created by the same GPU instance");if(n.graphical)throw new Error("graphical kernels are not supported inside pipelines");if(n.subKernels&&n.subKernels.length>0)throw new Error("kernel maps are not supported inside pipelines");if(!n.output)throw new Error("kernels called inside a pipeline must have a fixed output size");let r=this.kernelIndexes.get(e);void 0===r&&(r=this.kernels.length,this.kernels.push(e),this.kernelIndexes.set(e,r));const s=new Array(t.length);for(let e=0;ef(e,t)):e}function m(e){for(let t=0;t{if(this.destroyed)throw new Error(u);if(this.plan||(this.plan=this._buildPlan(),this._executor=void 0),void 0===this._executor&&await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;if(this._dropExecutor(),e.recompilable){if(await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;this._dropExecutor(),this._degrade(e.message)}}else this._degrade(e.message)}return this._executeGeneric(this.plan,t,r)}),i=()=>{this._inFlight--,n.length>0&&m(n)};return s.then(i,i),this._tail=s.then(b,b),s}_guardAsync(e){return e&&"function"==typeof e.then?e.then(null,e=>{throw this._dropExecutor(),e}):e}setConstants(e){this.constants=Object.assign({},e||{});const t=()=>{this._releasePlan()};return this._tail=this._tail.then(t,t),this}destroy(){if(this.destroyed=!0,this.gpu&&this.gpu.pipelines){const e=this.gpu.pipelines.indexOf(this);-1!==e&&this.gpu.pipelines.splice(e,1)}this._executor&&"function"==typeof this._executor.abortRuns&&this._executor.abortRuns(new Error(u));const e=()=>{this._releasePlan()},t=this._tail.then(e,e);return this._tail=t,t}_buildPlan(){const e=new d(this.gpu),t=new Array(this.argumentCount);for(let n=0;n({key:n,binding:e.bindValue(t)}))};if(t instanceof c)throw new Error(h);if("object"==typeof t&&!ArrayBuffer.isView(t)){if("function"==typeof t.then)throw new Error(l);const n=Object.getPrototypeOf(t);if(n!==Object.prototype&&null!==n)throw new Error(o);const r=[];for(const n in t)t.hasOwnProperty(n)&&r.push({key:n,binding:e.bindValue(t[n])});if(0===r.length)throw new Error(o);return{kind:"object",entries:r}}throw new Error(o)}(e,r),i=function(e,t){const n=new Array(e.length).fill(-1);for(let t=0;te.binding)),a=e.kernels.map(e=>({shortcut:e,clone:this._cloneKernel(e)}));return{steps:e.steps,buffers:i,results:s,kernels:a,held:e.held,genericClones:new Map}}_genericClone(e,t){const n=t.argBindings.map(e=>"step"===e.source?"T":"pipelineArg"===e.source?"a"+e.index:"l").join(","),r=t.kernel+":"+t.outputBuffer+":"+n;let s=e.genericClones.get(r);return s||(s=this._cloneKernel(e.kernels[t.kernel].clone,{immutable:!1,dynamicArguments:!1}),e.genericClones.set(r,s)),s}_prepareExecutor(e){if(this._fusionDisabled)return void(this._executor=!1);const t=this.plan.kernels;if(t.length>0&&"webgpu"===t[0].clone.kernel.constructor.mode){const{WebGPUPipelineExecutor:t}=ct();return t.compile(this,this.plan,e).then(e=>{this._executor=e,this.executorKind=e.kind,this.fallbackReason=null},e=>{this._degrade(e&&e.message||"fused executor unavailable")})}try{const{WebAssemblyPipelineExecutor:t}=ht();this._executor=t.compile(this,this.plan,e),this.executorKind=this._executor.kind,this.fallbackReason=null}catch(e){this._degrade(e&&e.message||"fused executor unavailable")}}_dropExecutor(){this._executor&&this._executor.destroy(),this._executor=void 0}_degrade(e){this._executor=!1,this.executorKind="generic",this.fallbackReason=e}_cloneKernel(e,t){const n=e.kernel,r=Object.assign({output:Array.from(n.output),pipeline:!0,immutable:!0,dynamicArguments:!0},t||{}),s=["constants","constantTypes","precision","loopMaxIterations","strictIntegers","fixIntegerDivisionAccuracy","optimizeFloatMemory","tactic","functions","nativeFunctions","injectedNative","debug","randomSeed","returnType","loopUnrollLimit","_optimizerDisabled","_inliningDisabled"];n.declaredArgumentTypes&&(r.argumentTypes=n.declaredArgumentTypes.slice());for(let e=0;e1?"function (v) { return v[this.thread.z][this.thread.y][this.thread.x]; }":t[1]>1?"function (v) { return v[this.thread.y][this.thread.x]; }":"function (v) { return v[this.thread.x]; }",a=t[2]>1?[t[0],t[1],t[2]]:t[1]>1?[t[0],t[1]]:[t[0]];s=this.gpu.createKernel(i,{output:a,pipeline:!0,immutable:!1}),e.genericClones.set(r,s)}return s(n)}_genericEagerUploadsPay(e){return 0!==e.kernels.length&&"gpu"===e.kernels[0].clone.kernel.constructor.mode}_eagerUploads(e,t){const r=new Array(t.length).fill(null);for(let s=0;s0?e.kernels[0].clone.kernel.constructor.mode:null,a="gpu"===i||"webgpu"===i,o=r||new Array(t.length).fill(null);if(a&&!r)for(let r=0;r{const{utils:n}=i(),{Input:s}=r(),{getActiveTrace:a}=pt();function o(e,t){if(t.kernel)return void(t.kernel=e);const r=n.allPropertiesOf(e);for(let n=0;nt.kernel[s]),t.__defineSetter__(s,e=>{t.kernel[s]=e})))}t.kernel=e}t.exports={kernelRunShortcut:function(e){function t(t){e.build.apply(e,t),e.checkArgumentTypes(t);let r=e.switchingKernels?void 0:e.run.apply(e,t);for(let s=0;e.switchingKernels;s++){if(s>=4){const t=e.resetSwitchingKernels();throw new Error(`this kernel cannot run the arguments it was given (${n(t)}); it did not settle on a kernel for them after 4 attempts. Create a separate kernel for this call's argument types.`)}const i=e.resetSwitchingKernels(),a=e.onRequestSwitchKernel(i,t,e);p.kernel=e=a,a.checkArgumentTypes(t),r=a.switchingKernels?void 0:a.run.apply(a,t),a.fallbackRequested&&(r=e.run.apply(e,t))}return r}function n(e){return e&&e.length?e.map(e=>"argumentTypeMismatch"===e.type?`argument ${e.index} is now ${e.needed}`:e.type).join(", "):"unknown reason"}function r(n){if(e.onAsyncModeUpgrade){const t=e.onAsyncModeUpgrade;e.onAsyncModeUpgrade=null;const s=l(n);return t(s,e).then(e=>(e&&p.replaceKernel(e),r(s)))}try{if(!0===e.constructor.isAsync)return e.build.apply(e,n),Promise.resolve(e.run.apply(e,n));for(let e=0;er(e));const s=t(n);return e.renderKernels?Promise.resolve(e.renderKernels()):e.renderOutput?e.renderOutputAsync?e.renderOutputAsync():Promise.resolve(e.renderOutput()):Promise.resolve(s)}catch(e){return Promise.reject(e)}}function i(e){return Boolean(e)&&"WebGPUBuffer"===e.type}function u(e){const t=l(e),n=[];for(let e=0;e{t[r]=e}))}return Promise.all(n).then(()=>t)}function l(e){const t=new Array(e.length);for(let n=0;n{try{e(c.apply(this,arguments))}catch(e){t(e)}})},p.replaceKernel=function(t){o(e=t,p)},o(e,p),p}}}),ft=e((e,n)=>{const{gpuMock:r}=t(),{utils:s}=i(),{Kernel:o}=a(),{CPUKernel:u}=d(),{HeadlessGLKernel:l}=ve(),{WebGL2Kernel:h}=tt(),{WebGLKernel:c}=be(),{WebGPUKernel:p}=it(),{WebAssemblyKernel:f}=lt(),{kernelRunShortcut:m}=dt(),{Pipeline:g}=pt(),y=[l,h,c,f],x=["gpu","cpu"],b={headlessgl:l,webgl2:h,webgl:c,webgpu:p,webasm:f};let v=!0;function S(e){if(!e)return{};const t=Object.assign({},e);return e.hasOwnProperty("floatOutput")&&(s.warnDeprecated("setting","floatOutput","precision"),t.precision=e.floatOutput?"single":"unsigned"),e.hasOwnProperty("outputToTexture")&&(s.warnDeprecated("setting","outputToTexture","pipeline"),t.pipeline=Boolean(e.outputToTexture)),e.hasOwnProperty("outputImmutable")&&(s.warnDeprecated("setting","outputImmutable","immutable"),t.immutable=Boolean(e.outputImmutable)),e.hasOwnProperty("floatTextures")&&(s.warnDeprecated("setting","floatTextures","optimizeFloatMemory"),t.optimizeFloatMemory=Boolean(e.floatTextures)),t}n.exports={GPU:class e{static disableValidation(){v=!1}static enableValidation(){v=!0}static get isGPUSupported(){return y.some(e=>e.isSupported)}static get isKernelMapSupported(){return y.some(e=>e.isSupported&&e.features.kernelMap)}static get isOffscreenCanvasSupported(){return"undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas||"undefined"!=typeof importScripts}static get isWebGLSupported(){return c.isSupported}static get isWebGL2Supported(){return h.isSupported}static get isHeadlessGLSupported(){return l.isSupported}static get isWebGPUSupported(){return p.isSupported}static isWebGPUAvailable(){return p.isSupported?navigator.gpu.requestAdapter().then(e=>null!==e,()=>!1):Promise.resolve(!1)}static get isWebAssemblySupported(){return f.isSupported}static get isCanvasSupported(){return"undefined"!=typeof HTMLCanvasElement}static get isGPUHTMLImageArraySupported(){return h.isSupported}static get isSinglePrecisionSupported(){return y.some(e=>e.isSupported&&e.features.isFloatRead&&e.features.isTextureFloat)}constructor(t){if(t=t||{},this.canvas=t.canvas||null,this.context=t.context||null,this.mode=t.mode,this.Kernel=null,this._webGPUDecision=null,"async"===t.mode&&(p.isSupported?e.isWebGPUAvailable().then(e=>{this._webGPUDecision=e},()=>{this._webGPUDecision=!1}):this._webGPUDecision=!1),this.kernels=[],this.pipelines=[],this.functions=[],this.nativeFunctions=[],this.injectedNative=null,"dev"!==this.mode){if(this.chooseKernel(),t.functions)for(let e=0;en.argumentTypes[e]));const l=this;function h(e){console.warn("Falling back to CPU"+(y.fallbackReason?`: ${y.fallbackReason}`:""));const n=new u(t,{argumentTypes:y.argumentTypes,constantTypes:y.constantTypes,graphical:y.graphical,loopMaxIterations:y.loopMaxIterations,constants:y.constants,dynamicOutput:y.dynamicOutput,dynamicArgument:y.dynamicArguments,output:y.output,precision:y.precision,pipeline:y.pipeline,immutable:y.immutable,optimizeFloatMemory:y.optimizeFloatMemory,fixIntegerDivisionAccuracy:y.fixIntegerDivisionAccuracy,functions:y.functions,nativeFunctions:y.nativeFunctions,injectedNative:y.injectedNative,subKernels:y.subKernels,strictIntegers:y.strictIntegers,_optimizerDisabled:y._optimizerDisabled,loopUnrollLimit:y.loopUnrollLimit,randomSeed:y.randomSeed,debug:y.debug,asyncMode:y.asyncMode,onRequestFallback:h,onRequestSwitchKernel:c,canvas:y.graphical&&!y.context?y.canvas:null});n.fallbackReason=y.fallbackReason,n.build.apply(n,e);const r=n.run.apply(n,e);return y.replaceKernel(n),!l.canvas&&n.canvas&&(l.canvas=n.canvas),!l.context&&n.context&&(l.context=n.context),r}function c(e,n,r){r.debug&&console.warn("Switching kernels");let s=null;if(r.signature&&!a[r.signature]&&(a[r.signature]=r),r.dynamicOutput)for(let t=e.length-1;t>=0;t--){const n=e[t];"outputPrecisionMismatch"===n.type&&(s=n.needed)}const o=r.constructor,u=o.getArgumentTypes(r,n),l=o.getSignature(r,u),p=a[l];if(p)return p.onActivate(r),p;const d=a[l]=new o(t,{argumentTypes:u,constantTypes:r.constantTypes,graphical:r.graphical,loopMaxIterations:r.loopMaxIterations,constants:r.constants,dynamicOutput:r.dynamicOutput,dynamicArgument:r.dynamicArguments,context:r.context,canvas:r.canvas,output:s||r.output,precision:r.precision,pipeline:r.pipeline,immutable:r.immutable,optimizeFloatMemory:r.optimizeFloatMemory,fixIntegerDivisionAccuracy:r.fixIntegerDivisionAccuracy,functions:r.functions,nativeFunctions:r.nativeFunctions,injectedNative:r.injectedNative,subKernels:r.subKernels,strictIntegers:r.strictIntegers,_optimizerDisabled:r._optimizerDisabled,loopUnrollLimit:r.loopUnrollLimit,randomSeed:r.randomSeed,debug:r.debug,asyncMode:r.asyncMode,gpu:r.gpu,validate:v,returnType:r.returnType,tactic:r.tactic,onRequestFallback:h,onRequestSwitchKernel:c,texture:r.texture,mappedTextures:r.mappedTextures,drawBuffersMap:r.drawBuffersMap});return d.build.apply(d,n),y.replaceKernel(d),i.push(d),d}const d=Object.assign({context:this.context,canvas:this.canvas,functions:this.functions,nativeFunctions:this.nativeFunctions,injectedNative:this.injectedNative,gpu:this,validate:v,onRequestFallback:h,onRequestSwitchKernel:c},o);"async"===this.mode&&(d.asyncMode=!0);let f,g=this.Kernel;"async"===this.mode&&o.graphical&&!0===this._webGPUDecision&&(g=p,d.canvas===this.canvas&&(d.canvas=o.canvas||null),d.context===this.context&&(d.context=o.context||null),d.asyncMode=!0);try{f=new g(t,d)}catch(e){if(g===this.Kernel)throw e;f=new this.Kernel(t,Object.assign({},d,{canvas:this.canvas,context:this.context}))}const y=m(f);if("async"===this.mode&&p.isSupported&&!(f instanceof p)){const n=this;f.onAsyncModeUpgrade=function(r,s){return e.isWebGPUAvailable().then(e=>{if(!e)return null;if(s.graphical)return s.debug&&console.warn("webgpu upgrade declined: graphical kernels keep their canvas"),null;let a;try{a=new p(t,{functions:s.functions,nativeFunctions:s.nativeFunctions,injectedNative:s.injectedNative,gpu:n,validate:v,asyncMode:!0,output:s.output,pipeline:s.pipeline,immutable:s.immutable,dynamicOutput:s.dynamicOutput,dynamicArguments:!0,loopMaxIterations:s.loopMaxIterations,constants:s.constants,constantTypes:s.constantTypes,argumentTypes:s.argumentTypes,precision:s.precision,tactic:s.tactic,strictIntegers:s.strictIntegers,_optimizerDisabled:s._optimizerDisabled,loopUnrollLimit:s.loopUnrollLimit,fixIntegerDivisionAccuracy:s.fixIntegerDivisionAccuracy,subKernels:s.subKernels,graphical:s.graphical,debug:s.debug}),a.build.apply(a,r)}catch(e){return s.debug&&console.warn("webgpu upgrade declined: "+e.message),null}return a._buildPromise.then(()=>(i.push(a),a),e=>(s.debug&&console.warn("webgpu upgrade declined: "+e.message),a.destroy(),null))},()=>null)}}return this.canvas||(this.canvas=f.canvas),this.context||(this.context=f.context),i.push(f),y}createPipeline(e,t){if("function"!=typeof e)throw new Error("createPipeline requires an orchestration function");if("dev"===this.mode)throw new Error("createPipeline is not supported in dev mode");const n=new g(this,e,t);this.pipelines.push(n);const r=function(){return n.call(arguments)};return r.pipeline=n,r.setConstants=function(e){return n.setConstants(e),r},r.destroy=function(){return n.destroy()},Object.defineProperty(r,"executorKind",{get:()=>n.executorKind}),Object.defineProperty(r,"fallbackReason",{get:()=>n.fallbackReason}),Object.defineProperty(r,"plan",{get:()=>n.plan}),Object.defineProperty(r,"backend",{get:()=>{const e=n.executorKind;if("fused-sync"===e||"fused-threaded"===e)return"webasm";if("fused-encoder"===e)return"webgpu";const t=n.plan;if(!t)return null;for(const[e,n]of t.genericClones)if(0!==e.indexOf("up:"))return n.kernel.constructor.mode;return t.kernels.length>0?t.kernels[0].clone.kernel.constructor.mode:null}}),r}createKernelMap(){let e,t;const n=typeof arguments[arguments.length-2];if("function"===n||"string"===n?(e=arguments[arguments.length-2],t=arguments[arguments.length-1]):e=arguments[arguments.length-1],!("dev"===this.mode||this.Kernel.isSupported&&this.Kernel.features.kernelMap)){if("webgpu"===this.Kernel.mode)throw new Error("WebGPU backend does not yet support createKernelMap");if(this.mode&&x.indexOf(this.mode)<0&&"webasm"!==this.Kernel.mode)throw new Error(`kernelMap not supported on ${this.Kernel.name}`)}const r=S(t);if(t&&"object"==typeof t.argumentTypes&&(r.argumentTypes=Object.keys(t.argumentTypes).map(e=>t.argumentTypes[e])),Array.isArray(arguments[0])){r.subKernels=[];const e=arguments[0];for(let t=0;t0)throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.');return this.nativeFunctions.push(Object.assign({name:e,source:t},n)),this}injectNative(e){return this.injectedNative=e,this}destroy(){return new Promise((e,t)=>{this.kernels||e(),setTimeout(()=>{try{let n=Promise.resolve();if(this.pipelines){const e=this.pipelines.slice();n=Promise.all(e.map(e=>Promise.resolve(e.destroy()).catch(()=>{})))}const r=()=>{try{const e=this.kernels.slice();for(let t=0;t{const{utils:n}=i();t.exports={alias:function(e,t){const r=t.toString();return new Function(`return function ${e} (${n.getArgumentNamesFromString(r).join(", ")}) {\n ${n.getFunctionBodyFromString(r)}\n}`)()}}}),gt=e((e,t)=>{const{GPU:n}=ft(),{alias:o}=mt(),{utils:p}=i(),{Input:f,input:m}=r(),{Texture:g}=s(),{FunctionBuilder:y}=u(),{FunctionNode:x}=h(),{CPUFunctionNode:b}=c(),{CPUKernel:v}=d(),{HeadlessGLKernel:S}=ve(),{WebGLFunctionNode:T}=R(),{WebGLKernel:A}=be(),{kernelValueMaps:w}=xe(),{WebGL2FunctionNode:E}=Se(),{WebGL2Kernel:I}=tt(),{kernelValueMaps:_}=et(),{WGSLFunctionNode:k}=nt(),{WebGPUKernel:L}=it(),{WebGPUContext:F}=rt(),{WebGPUBufferResult:D}=st(),{WebAssemblyFunctionNode:$}=ot(),{WebAssemblyKernel:C}=lt(),{GLKernel:N}=M(),{Kernel:O}=a(),{FunctionTracer:z}=l();t.exports={alias:o,CPUFunctionNode:b,CPUKernel:v,GPU:n,FunctionBuilder:y,FunctionNode:x,HeadlessGLKernel:S,Input:f,input:m,Texture:g,utils:p,WebGL2FunctionNode:E,WebGL2Kernel:I,webGL2KernelValueMaps:_,WebGLFunctionNode:T,WebGLKernel:A,webGLKernelValueMaps:w,WGSLFunctionNode:k,WebGPUKernel:L,WebGPUContext:F,WebGPUBufferResult:D,WebAssemblyFunctionNode:$,WebAssemblyKernel:C,GLKernel:N,Kernel:O,FunctionTracer:z,plugins:{mathRandom:G()}}});return e((e,t)=>{const n=gt(),r=n.GPU;for(const e in n)n.hasOwnProperty(e)&&"GPU"!==e&&(r[e]=n[e]);function s(e){e.GPU&&e.GPU.prototype&&e.GPU.prototype.createKernel||Object.defineProperty(e,"GPU",{configurable:!0,get:()=>r,set(){}})}r.GPU=r,"undefined"!=typeof window&&s(window),"undefined"!=typeof self&&s(self),t.exports=r})()}); \ No newline at end of file diff --git a/dist/gpu-browser.js b/dist/gpu-browser.js index 8d1c2130..dceb4d62 100644 --- a/dist/gpu-browser.js +++ b/dist/gpu-browser.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.23.0 - * @date Mon Aug 03 2026 18:12:01 GMT+0800 (Singapore Standard Time) + * @date Wed Aug 05 2026 10:06:18 GMT+0800 (Singapore Standard Time) * * @license MIT * The MIT License @@ -5308,6 +5308,10 @@ this.optimizeFloatMemory = null; this.strictIntegers = false; this.fixIntegerDivisionAccuracy = null; + this._optimizerDisabled = false; + this._inliningDisabled = false; + this.localizeThreadCoordinates = false; + this.loopUnrollLimit = 8; this.randomSeed = null; this.built = false; this.signature = null; @@ -5456,6 +5460,10 @@ this.loopMaxIterations = max; return this; } + setLoopUnrollLimit(limit) { + this.loopUnrollLimit = limit; + return this; + } setConstants(constants) { this.constants = constants; return this; @@ -5576,6 +5584,18 @@ this.fallbackReason = reason || null; return this.onRequestFallback(args); } + buildWithOptimizer(work) { + if (this._optimizerDisabled) return work(); + try { + return work(); + } catch (e) { + if (!e || !e.isOptimizerFailure) throw e; + this._optimizerDisabled = true; + this.fallbackReason = `compiler optimizations disabled: ${e.message}`; + console.warn(`gpu.js: compiling this kernel with compiler optimizations threw (${e.message}); rebuilding with them off. Please report this at https://github.com/gpujs/gpu.js/issues`); + return work(); + } + } validateSettings() { throw new Error(`"validateSettings" not defined on ${this.constructor.name}`); } @@ -5652,72 +5672,1748 @@ argumentTypes[i] = utils.getVariableType(arg, kernel.strictIntegers); break; - default: - argumentTypes[i] = utils.typeFitsValue(type, arg) ? type : utils.getVariableType(arg, kernel.strictIntegers); - } + default: + argumentTypes[i] = utils.typeFitsValue(type, arg) ? type : utils.getVariableType(arg, kernel.strictIntegers); + } + } + return argumentTypes; + } + static getSignature(kernel, argumentTypes) { + throw new Error(`"getSignature" not implemented on ${this.name}`); + } + functionToIGPUFunction(source, settings = {}) { + if (typeof source !== "string" && typeof source !== "function") throw new Error("source not a string or function"); + const sourceString = typeof source === "string" ? source : source.toString(); + let argumentTypes = []; + if (Array.isArray(settings.argumentTypes)) argumentTypes = settings.argumentTypes; else if (typeof settings.argumentTypes === "object") { + const argumentNames = utils.getArgumentNamesFromString(sourceString); + argumentTypes = argumentNames.map(name => settings.argumentTypes[name]) || []; + const keys = Object.keys(settings.argumentTypes); + if (keys.length > 0 && argumentNames.length > 0 && argumentTypes.every(type => type === void 0)) throw new Error(`argumentTypes keys [${keys.join(", ")}] match none of the function's parameters [${argumentNames.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${keys.map(k => settings.argumentTypes[k]).join("', '")}']`); + } else argumentTypes = settings.argumentTypes || []; + return { + name: settings.name || utils.getFunctionNameFromString(sourceString) || (typeof source === "function" && source.name ? source.name : null), + source: sourceString, + argumentTypes: argumentTypes, + returnType: settings.returnType || null + }; + } + onActivate(previousKernel) {} + switchKernels(reason) { + if (this.switchingKernels) this.switchingKernels.push(reason); else this.switchingKernels = [ reason ]; + } + resetSwitchingKernels() { + const existingValue = this.switchingKernels; + this.switchingKernels = null; + return existingValue; + } + checkArgumentTypes(args) { + if (!this.argumentTypes) return; + const length = Math.min(args.length, this.argumentTypes.length); + for (let i = 0; i < length; i++) if (!utils.typeFitsValue(this.argumentTypes[i], args[i])) this.switchKernels({ + type: "argumentTypeMismatch", + index: i, + needed: utils.getVariableType(args[i], this.strictIntegers) + }); + } + }; + function splitArgumentTypes(argumentTypesObject) { + const argumentNames = Object.keys(argumentTypesObject); + const argumentTypes = []; + for (let i = 0; i < argumentNames.length; i++) { + const argumentName = argumentNames[i]; + argumentTypes.push(argumentTypesObject[argumentName]); + } + return { + argumentTypes: argumentTypes, + argumentNames: argumentNames + }; + } + module.exports = { + Kernel: Kernel + }; + }); + var require_optimizer = __commonJSMin((exports, module) => { + let syntheticNodeId = 1610612736; + function stampSynthetic(node, source) { + node.start = syntheticNodeId++; + node.end = syntheticNodeId++; + if (source && source.loc) node.loc = source.loc; + return node; + } + const scalarTypes = [ "Number", "Float", "Integer" ]; + const thisWrite = "@this"; + const indexedReadSignatures = [ "value[]", "value[][]", "value[][][]", "value[][][][]", "this.constants.value[]", "this.constants.value[][]", "this.constants.value[][][]", "this.constants.value[][][][]" ]; + function optimize(functionNode, ast, settings) { + if (!ast || !ast.body || ast.body.type !== "BlockStatement") return ast; + const context = new OptimizerContext(functionNode, ast, settings || {}); + processBlock(context, ast.body); + inlineBlock(context, ast.body); + unrollBlock(context, ast.body); + return ast; + } + var OptimizerContext = class { + constructor(functionNode, ast, settings) { + this.functionNode = functionNode; + this.ast = ast; + this.loopUnrollLimit = typeof settings.loopUnrollLimit === "number" ? settings.loopUnrollLimit : 8; + this.lookupInlineTarget = settings.lookupInlineTarget || null; + this.inlineTargets = new Map; + this.inlineCount = 0; + this.mutatedNames = collectMutatedNames(ast.body); + this.usedNames = collectUsedNames(ast); + this.hoistCount = 0; + } + freshName() { + let name; + do { + name = `optHoist${this.hoistCount++}`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + freshInlineName(suffix) { + let name; + do { + name = `optIn${this.inlineCount++}_${suffix}`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + inlineTarget(name) { + if (!this.lookupInlineTarget) return null; + if (this.inlineTargets.has(name)) return this.inlineTargets.get(name); + let entry = null; + try { + entry = this.lookupInlineTarget(name) || null; + } catch (e) { + entry = null; + } + this.inlineTargets.set(name, entry); + return entry; + } + isImmutableArrayRoot(name) { + if (this.mutatedNames.has(name)) return false; + const {argumentNames: argumentNames} = this.functionNode; + return Boolean(argumentNames) && argumentNames.indexOf(name) > -1; + } + readElementType(ast, signature) { + const rootType = this.readRootType(ast, signature); + if (!rootType) return null; + try { + return this.functionNode.getLookupType(rootType); + } catch (e) { + return null; + } + } + readRootType(ast, signature) { + const {functionNode: functionNode} = this; + if (signature.indexOf("this.constants.") === 0) { + if (this.mutatedNames.has(thisWrite)) return null; + const name = constantReadName(ast, signature); + if (!name) return null; + const type = functionNode.constantTypes ? functionNode.constantTypes[name] : null; + return type === "Float" ? "Number" : type || null; + } + const root = memberRoot(ast); + if (!root || root.type !== "Identifier") return null; + if (!this.isImmutableArrayRoot(root.name)) return null; + const index = functionNode.argumentNames.indexOf(root.name); + return (functionNode.argumentTypes ? functionNode.argumentTypes[index] : null) || null; + } + }; + function walk(node, visit) { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walk(node[i], visit); + return; + } + if (typeof node.type !== "string") return; + visit(node); + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") walk(child, visit); + } + } + function walkOwn(node, visit) { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walkOwn(node[i], visit); + return; + } + if (typeof node.type !== "string") return; + if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") return; + visit(node); + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") walkOwn(child, visit); + } + } + function collectMutatedNames(ast) { + const names = new Set; + const addTarget = target => { + let node = target; + while (node && node.type === "MemberExpression") node = node.object; + if (node && node.type === "Identifier") names.add(node.name); + if (node && node.type === "ThisExpression") names.add(thisWrite); + }; + walk(ast, node => { + switch (node.type) { + case "AssignmentExpression": + addTarget(node.left); + break; + + case "UpdateExpression": + addTarget(node.argument); + break; + + case "VariableDeclarator": + if (node.id && node.id.type === "Identifier") names.add(node.id.name); + break; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + if (node.id && node.id.name) names.add(node.id.name); + for (let i = 0; i < node.params.length; i++) if (node.params[i].type === "Identifier") names.add(node.params[i].name); + break; + } + }); + return names; + } + function collectUsedNames(ast) { + const names = new Set; + walk(ast, node => { + if (node.type === "Identifier") names.add(node.name); + }); + return names; + } + function memberRoot(ast) { + let node = ast; + while (node && node.type === "MemberExpression") node = node.object; + return node; + } + function constantReadName(ast, signature) { + let depth = (signature.match(/\[\]/g) || []).length; + let node = ast; + while (depth-- > 0) { + if (!node || node.type !== "MemberExpression") return null; + node = node.object; + } + return node && node.property && node.property.name ? node.property.name : null; + } + function processBlock(context, block) { + const body = block.body; + for (let i = 0; i < body.length; i++) { + const prefix = processStatement(context, body[i]); + if (prefix && prefix.length > 0) { + body.splice(i, 0, ...prefix); + i += prefix.length; + } + } + } + function processStatement(context, statement) { + switch (statement.type) { + case "BlockStatement": + processBlock(context, statement); + return null; + + case "IfStatement": + processBranch(context, statement, "consequent"); + processBranch(context, statement, "alternate"); + return null; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) { + const block = { + type: "BlockStatement", + body: statement.cases[i].consequent + }; + processBlock(context, block); + statement.cases[i].consequent = block.body; + } + return null; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + processBranch(context, statement, "body"); + return hoistFromLoop(context, statement); + + default: + return null; + } + } + function processBranch(context, statement, key) { + const branch = statement[key]; + if (!branch) return; + if (branch.type === "BlockStatement") { + processBlock(context, branch); + return; + } + const prefix = processStatement(context, branch); + if (prefix && prefix.length > 0) statement[key] = stampSynthetic({ + type: "BlockStatement", + body: prefix.concat([ branch ]) + }, branch); + } + function hoistFromLoop(context, loop) { + const varying = collectMutatedNames(loop); + const entries = []; + collectReachable(loop.body, entries); + if (entries.length === 0) return []; + const faultable = context.functionNode.readsCanFault && !loopIsAlwaysEntered(loop); + const hoisted = []; + const relocated = new Set; + const cache = new Map; + for (let i = 0; i < entries.length; i++) { + const {statement: statement} = entries[i]; + if (statement.optimizerHoist && isInvariant(context, statement.declarations[0].init, varying) && !(faultable && canFault(context, statement.declarations[0].init))) { + const key = expressionKey(statement.declarations[0].init); + hoisted.push(statement); + relocated.add(statement); + if (key) cache.set(key, statement.declarations[0].id.name); + continue; + } + replaceInvariantReads(context, statement, varying, faultable, cache, hoisted); + } + if (relocated.size > 0) for (let i = 0; i < entries.length; i++) { + const {list: list} = entries[i]; + if (!list.some(statement => relocated.has(statement))) continue; + const kept = list.filter(statement => !relocated.has(statement)); + list.length = 0; + for (let j = 0; j < kept.length; j++) list.push(kept[j]); + } + return hoisted; + } + function collectReachableList(list, entries) { + for (let i = 0; i < list.length; i++) { + const statement = list[i]; + switch (statement.type) { + case "ExpressionStatement": + case "VariableDeclaration": + entries.push({ + list: list, + statement: statement + }); + break; + + case "EmptyStatement": + case "DebuggerStatement": + break; + + case "BlockStatement": + if (!collectReachableList(statement.body, entries)) return false; + break; + + case "IfStatement": + case "SwitchStatement": + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + if (containsExit(statement)) return false; + break; + + default: + return false; + } + } + return true; + } + function collectReachable(body, entries) { + if (!body) return false; + if (body.type === "BlockStatement") return collectReachableList(body.body, entries); + return collectReachableList([ body ], entries); + } + function containsExit(statement) { + let found = false; + const visit = (node, inBreakable, inContinuable) => { + if (!node || typeof node !== "object" || found) return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "ReturnStatement": + case "ThrowStatement": + found = true; + return; + + case "BreakStatement": + if (node.label || !inBreakable) found = true; + return; + + case "ContinueStatement": + if (node.label || !inContinuable) found = true; + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + + case "SwitchStatement": + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child, inBreakable, inContinuable); + } + }; + visit(statement, false, false); + return found; + } + function replaceInvariantReads(context, statement, varying, faultable, cache, hoisted) { + const visit = (node, key) => { + const child = node[key]; + if (!child || typeof child !== "object") return; + if (Array.isArray(child)) { + for (let i = 0; i < child.length; i++) visit(child, i); + return; + } + if (typeof child.type !== "string") return; + switch (child.type) { + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return; + + case "ConditionalExpression": + visit(child, "test"); + return; + + case "LogicalExpression": + visit(child, "left"); + return; + + case "MemberExpression": + if (isHoistableRead(context, child, varying) && !(faultable && canFault(context, child))) { + node[key] = referenceFor(context, child, cache, hoisted); + return; + } + if (child.computed) visit(child, "property"); + if (child.object && child.object.type !== "MemberExpression") visit(child, "object"); + return; + } + for (const childKey in child) { + if (childKey === "loc" || childKey === "range" || childKey === "parent") continue; + const grandChild = child[childKey]; + if (grandChild && typeof grandChild === "object") visit(child, childKey); + } + }; + visit({ + statement: statement + }, "statement"); + } + function referenceFor(context, read, cache, hoisted) { + const key = expressionKey(read); + if (key && cache.has(key)) return stampSynthetic({ + type: "Identifier", + name: cache.get(key) + }, read); + const name = context.freshName(); + const declaration = stampSynthetic({ + type: "VariableDeclaration", + kind: "const", + declarations: [ stampSynthetic({ + type: "VariableDeclarator", + id: stampSynthetic({ + type: "Identifier", + name: name + }, read), + init: read + }, read) ] + }, read); + declaration.optimizerHoist = true; + hoisted.push(declaration); + if (key) cache.set(key, name); + return stampSynthetic({ + type: "Identifier", + name: name + }, read); + } + function canFault(context, ast) { + let found = false; + walk(ast, node => { + if (found || node.type !== "MemberExpression") return; + const signature = context.functionNode.getVariableSignature(node); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return; + if (!context.functionNode.readsFaultAtOneLevel && (signature.match(/\[\]/g) || []).length < 2) return; + if (context.readRootType(node, signature) === "Input") return; + found = true; + }); + return found; + } + function loopIsAlwaysEntered(loop) { + if (loop.type === "DoWhileStatement") return true; + if (loop.type !== "ForStatement") return false; + if (!loop.test) return true; + const {test: test} = loop; + if (test.type !== "BinaryExpression" || test.left.type !== "Identifier") return false; + const limit = literalNumber(test.right); + if (limit === null) return false; + const start = initialNumber(loop.init, test.left.name); + if (start === null) return false; + switch (test.operator) { + case "<": + return start < limit; + + case "<=": + return start <= limit; + + case ">": + return start > limit; + + case ">=": + return start >= limit; + + case "!==": + case "!=": + return start !== limit; + + default: + return false; + } + } + function literalNumber(ast) { + if (!ast) return null; + if (ast.type === "Literal" && typeof ast.value === "number") return ast.value; + if (ast.type === "UnaryExpression" && ast.operator === "-") { + const value = literalNumber(ast.argument); + return value === null ? null : -value; + } + return null; + } + function initialNumber(init, name) { + if (!init) return null; + if (init.type === "VariableDeclaration") { + for (let i = 0; i < init.declarations.length; i++) { + const declaration = init.declarations[i]; + if (declaration.id.type === "Identifier" && declaration.id.name === name) return literalNumber(declaration.init); + } + return null; + } + if (init.type === "AssignmentExpression" && init.operator === "=" && init.left.type === "Identifier" && init.left.name === name) return literalNumber(init.right); + return null; + } + function isHoistableRead(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return false; + const elementType = context.readElementType(ast, signature); + if (!elementType || scalarTypes.indexOf(elementType) === -1) return false; + return isInvariant(context, ast, varying); + } + function isInvariant(context, ast, varying) { + if (!ast || typeof ast !== "object") return false; + switch (ast.type) { + case "Literal": + return true; + + case "ThisExpression": + return true; + + case "Identifier": + return !varying.has(ast.name); + + case "UnaryExpression": + return ast.operator !== "delete" && ast.operator !== "typeof" && isInvariant(context, ast.argument, varying); + + case "BinaryExpression": + case "LogicalExpression": + return isInvariant(context, ast.left, varying) && isInvariant(context, ast.right, varying); + + case "ConditionalExpression": + return isInvariant(context, ast.test, varying) && isInvariant(context, ast.consequent, varying) && isInvariant(context, ast.alternate, varying); + + case "MemberExpression": + return isInvariantMember(context, ast, varying); + + default: + return false; + } + } + function isInvariantMember(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature) return false; + switch (signature) { + case "this.thread.value": + case "this.output.value": + return true; + + case "this.constants.value": + return !context.mutatedNames.has(thisWrite); + + case "value.value": + return context.functionNode.isAstMathVariable(ast); + + case "value[]": + case "value[][]": + case "value[][][]": + case "value[][][][]": + { + const root = memberRoot(ast); + if (!root || root.type !== "Identifier" || !context.isImmutableArrayRoot(root.name)) return false; + return everySubscriptInvariant(context, ast, varying); + } + + case "this.constants.value[]": + case "this.constants.value[][]": + case "this.constants.value[][][]": + case "this.constants.value[][][][]": + if (context.mutatedNames.has(thisWrite)) return false; + return everySubscriptInvariant(context, ast, varying); + + default: + return false; + } + } + function everySubscriptInvariant(context, ast, varying) { + let node = ast; + while (node && node.type === "MemberExpression") { + if (node.computed && !isInvariant(context, node.property, varying)) return false; + node = node.object; + } + return true; + } + function expressionKey(ast) { + if (!ast || typeof ast !== "object") return null; + switch (ast.type) { + case "Literal": + return `L${typeof ast.value}:${ast.value}`; + + case "ThisExpression": + return "this"; + + case "Identifier": + return `#${ast.name}`; + + case "MemberExpression": + { + const object = expressionKey(ast.object); + const property = expressionKey(ast.property); + if (object === null || property === null) return null; + return `M${ast.computed ? "[" : "."}(${object},${property})`; + } + + case "UnaryExpression": + { + const argument = expressionKey(ast.argument); + return argument === null ? null : `U${ast.operator}(${argument})`; + } + + case "BinaryExpression": + case "LogicalExpression": + { + const left = expressionKey(ast.left); + const right = expressionKey(ast.right); + if (left === null || right === null) return null; + return `B${ast.operator}(${left},${right})`; + } + + default: + return null; + } + } + const INLINE_MAX_HELPER_NODES = 320; + const INLINE_MAX_ADDED_NODES = 6e3; + const UNROLL_MAX_ADDED_NODES = 6e3; + const INLINE_MAX_STATEMENTS = 2e4; + function inlineBlock(context, block) { + if (!context.lookupInlineTarget) return; + block.body = inlineList(context, block.body); + } + function inlineList(context, list) { + const out = []; + const pending = list.slice(); + let guard = 0; + while (pending.length > 0) { + if (++guard > INLINE_MAX_STATEMENTS) throw new Error("optimizer: inlining did not converge"); + const statement = pending.shift(); + const prefix = []; + const expansion = inlineStatementOwn(context, statement, prefix); + if (expansion.expanded > 0) { + const replacement = expansion.consumed ? stampSynthetic({ + type: "EmptyStatement" + }, statement) : statement; + pending.unshift(...prefix, replacement); + continue; + } + inlineStatementChildren(context, statement); + out.push(statement); + } + return out; + } + function inlineStatementChildren(context, statement) { + switch (statement.type) { + case "BlockStatement": + inlineBlock(context, statement); + return; + + case "IfStatement": + statement.consequent = inlineBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = inlineBranch(context, statement.alternate); + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + statement.body = inlineBranch(context, statement.body); + return; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) statement.cases[i].consequent = inlineList(context, statement.cases[i].consequent); + return; + } + } + function inlineBranch(context, branch) { + if (!branch) return branch; + if (branch.type === "BlockStatement") { + inlineBlock(context, branch); + return branch; + } + const replacement = inlineList(context, [ branch ]); + if (replacement.length === 1 && replacement[0] === branch) return branch; + return stampSynthetic({ + type: "BlockStatement", + body: replacement + }, branch); + } + function inlineStatementOwn(context, statement, prefix) { + const sites = collectStatementSites(context, statement); + let consumed = false; + for (let i = 0; i < sites.length; i++) if (expandCall(context, sites[i], prefix)) consumed = true; + return { + expanded: sites.length, + consumed: consumed + }; + } + function collectStatementSites(context, statement) { + const scan = { + candidates: name => context.inlineTarget(name), + sites: [], + clean: true + }; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + return scan.sites; + } + function statementValueRoots(statement) { + switch (statement.type) { + case "ExpressionStatement": + return [ { + parent: statement, + key: "expression", + statementPosition: true + } ]; + + case "ReturnStatement": + return statement.argument ? [ { + parent: statement, + key: "argument" + } ] : []; + + case "IfStatement": + return [ { + parent: statement, + key: "test" + } ]; + + case "SwitchStatement": + return [ { + parent: statement, + key: "discriminant" + } ]; + + case "VariableDeclaration": + return declarationRoots(statement); + + case "ForStatement": + if (!statement.init) return []; + if (statement.init.type === "VariableDeclaration") return declarationRoots(statement.init); + return [ { + parent: statement, + key: "init" + } ]; + + default: + return []; + } + } + function declarationRoots(declaration) { + const roots = []; + for (let i = 0; i < declaration.declarations.length; i++) if (declaration.declarations[i].init) roots.push({ + parent: declaration.declarations[i], + key: "init" + }); + return roots; + } + function scanValue(parent, key, scan, statementPosition, objectPosition) { + const node = parent[key]; + if (!node || typeof node !== "object" || typeof node.type !== "string") return; + switch (node.type) { + case "Literal": + case "Identifier": + case "ThisExpression": + return; + + case "MemberExpression": + scanValue(node, "object", scan, false, node.object && node.object.type === "CallExpression"); + if (node.computed) scanValue(node, "property", scan, false); + return; + + case "UnaryExpression": + scanValue(node, "argument", scan, false); + return; + + case "BinaryExpression": + scanValue(node, "left", scan, false); + scanValue(node, "right", scan, false); + return; + + case "LogicalExpression": + scanValue(node, "left", scan, false); + scanConditional(node.right, scan); + return; + + case "ConditionalExpression": + scanValue(node, "test", scan, false); + scanConditional(node.consequent, scan); + scanConditional(node.alternate, scan); + return; + + case "ArrayExpression": + for (let i = 0; i < node.elements.length; i++) scanValue(node.elements, i, scan, false); + return; + + case "SequenceExpression": + for (let i = 0; i < node.expressions.length; i++) scanValue(node.expressions, i, scan, false); + return; + + case "AssignmentExpression": + if (node.left.type === "MemberExpression") scanValue(node, "left", scan, false); + scanValue(node, "right", scan, false); + scan.clean = false; + return; + + case "UpdateExpression": + scan.clean = false; + return; + + case "CallExpression": + { + for (let i = 0; i < node.arguments.length; i++) scanValue(node.arguments, i, scan, false); + const name = inlineCalleeName(node); + const entry = name ? scan.candidates(name) : null; + if (entry && !objectPosition) { + if (scan.clean && (entry.returnsValue || statementPosition)) { + scan.sites.push({ + parent: parent, + key: key, + node: node, + entry: entry, + statementPosition: statementPosition + }); + if (entry.hasEffects) scan.clean = false; + return; + } + scan.clean = false; + return; + } + if (!isPureMathCall(node)) scan.clean = false; + return; + } + + default: + scan.clean = false; + } + } + function scanConditional(node, scan) { + walk(node, child => { + if (child.type === "CallExpression") { + if (!isPureMathCall(child)) scan.clean = false; + return; + } + if (child.type === "AssignmentExpression" || child.type === "UpdateExpression") scan.clean = false; + }); + } + function inlineCalleeName(ast) { + return ast.callee && ast.callee.type === "Identifier" ? ast.callee.name : null; + } + function isPureMathCall(ast) { + const {callee: callee} = ast; + return Boolean(callee) && callee.type === "MemberExpression" && !callee.computed && callee.object && callee.object.type === "Identifier" && callee.object.name === "Math" && callee.property && callee.property.name !== "random"; + } + function expandCall(context, site, prefix) { + const {node: node, entry: entry, parent: parent, key: key} = site; + const bindings = new Map; + for (let i = 0; i < entry.params.length; i++) { + const param = entry.params[i]; + const argument = node.arguments[i]; + if (!entry.assignedParams.has(param) && isInlineAtom(context, argument)) { + bindings.set(param, { + atom: argument, + name: null + }); + continue; + } + const name = context.freshInlineName(param); + prefix.push(inlineDeclaration(entry.assignedParams.has(param) ? "let" : "const", name, argument)); + bindings.set(param, { + atom: null, + name: name + }); + } + for (let i = entry.params.length; i < node.arguments.length; i++) prefix.push(inlineDeclaration("const", context.freshInlineName("arg"), node.arguments[i])); + const renames = new Map; + entry.localNames.forEach(local => { + renames.set(local, context.freshInlineName(local)); + }); + const reduced = reduceReturns(cloneInlineNodes(context, entry.body, bindings, renames)); + if (!reduced) throw new Error(`optimizer: helper body no longer reduces`); + for (let i = 0; i < reduced.statements.length; i++) prefix.push(reduced.statements[i]); + if (site.statementPosition) { + if (reduced.value !== null) prefix.push(inlineDeclaration("const", context.freshInlineName("ret"), reduced.value)); + return true; + } + parent[key] = reduced.value; + return false; + } + function inlineDeclaration(kind, name, init) { + return stampSynthetic({ + type: "VariableDeclaration", + kind: kind, + declarations: [ stampSynthetic({ + type: "VariableDeclarator", + id: stampSynthetic({ + type: "Identifier", + name: name + }, init), + init: init + }, init) ] + }, init); + } + function isInlineAtom(context, ast) { + if (!ast || typeof ast !== "object") return false; + switch (ast.type) { + case "Literal": + return true; + + case "Identifier": + return true; + + case "UnaryExpression": + return (ast.operator === "-" || ast.operator === "+") && ast.argument.type === "Literal"; + + case "MemberExpression": + try { + switch (context.functionNode.getVariableSignature(ast)) { + case "this.thread.value": + case "this.output.value": + return true; + + case "this.constants.value": + return !context.mutatedNames.has(thisWrite); + + case "value.value": + return context.functionNode.isAstMathVariable(ast); + + default: + return false; + } + } catch (e) { + return false; + } + + default: + return false; + } + } + function cloneInlineNodes(context, nodes, bindings, renames) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneInlineNode(context, nodes[i], bindings, renames); + return result; + } + function cloneInlineNode(context, node, bindings, renames) { + if (!node || typeof node !== "object") return node; + if (Array.isArray(node)) return cloneInlineNodes(context, node, bindings, renames); + if (typeof node.type !== "string") return node; + if (node.type === "Identifier") { + const bound = bindings.get(node.name); + if (bound) return bound.atom ? cloneNode(context, bound.atom, null, 0) : stampSynthetic({ + type: "Identifier", + name: bound.name + }, node); + return stampSynthetic({ + type: "Identifier", + name: renames.get(node.name) || node.name + }, node); + } + const copy = {}; + const verbatimProperty = node.type === "MemberExpression" && !node.computed; + for (const key in node) { + if (key === "start" || key === "end") continue; + if (key === "loc" || key === "range" || key === "parent") { + copy[key] = node[key]; + continue; + } + copy[key] = verbatimProperty && key === "property" ? cloneNode(context, node[key], null, 0) : cloneInlineNode(context, node[key], bindings, renames); + } + return stampSynthetic(copy, node); + } + function reduceReturns(statements) { + let first = -1; + for (let i = 0; i < statements.length; i++) if (containsReturn(statements[i])) { + first = i; + break; + } + if (first === -1) return { + statements: statements, + value: null + }; + const value = tailExpression(statements, first); + if (value === null) return null; + return { + statements: statements.slice(0, first), + value: value + }; + } + function tailExpression(list, i) { + if (i >= list.length) return null; + const statement = list[i]; + if (statement.type === "ReturnStatement") { + if (i !== list.length - 1 || !statement.argument) return null; + return statement.argument; + } + if (statement.type !== "IfStatement") return null; + const consequent = branchExpression(statement.consequent); + if (consequent === null) return null; + let alternate; + if (statement.alternate) { + if (i !== list.length - 1) return null; + alternate = branchExpression(statement.alternate); + } else alternate = tailExpression(list, i + 1); + if (alternate === null) return null; + if (!isBranchSafe(consequent) || !isBranchSafe(alternate)) return null; + const consequentKind = branchLiteralKind(consequent); + const alternateKind = branchLiteralKind(alternate); + if (consequentKind !== "unknown" && alternateKind !== "unknown" && consequentKind !== alternateKind) return null; + return stampSynthetic({ + type: "ConditionalExpression", + test: statement.test, + consequent: consequent, + alternate: alternate + }, statement); + } + function branchLiteralKind(ast) { + if (!ast) return "unknown"; + if (ast.type === "Literal" && typeof ast.value === "number") return Number.isInteger(ast.value) ? "int" : "float"; + if (ast.type === "BinaryExpression" && "+-*/".indexOf(ast.operator) > -1) { + const left = branchLiteralKind(ast.left); + const right = branchLiteralKind(ast.right); + if (left === "float" || right === "float") return "float"; + if (left === "unknown" || right === "unknown") return "unknown"; + return ast.operator === "/" ? "unknown" : "int"; + } + return "unknown"; + } + function branchExpression(branch) { + if (!branch) return null; + return tailExpression(branch.type === "BlockStatement" ? branch.body : [ branch ], 0); + } + function containsReturn(ast) { + let found = false; + walk(ast, node => { + if (node.type === "ReturnStatement") found = true; + }); + return found; + } + function isBranchSafe(ast) { + let safe = true; + walk(ast, node => { + if (node.type === "CallExpression" && !isPureMathCall(node)) safe = false; + }); + return safe; + } + function buildInlinePlan(builder) { + const entries = new Map; + const kernel = builder.kernel || {}; + const allowedFree = new Set([ "Math", "Infinity" ]); + if (kernel.constants) for (const name in kernel.constants) allowedFree.add(name); + for (let i = 0; i < builder.nativeFunctionNames.length; i++) allowedFree.add(builder.nativeFunctionNames[i]); + for (const name in builder.functionMap) { + const node = builder.functionMap[name]; + if (!node) continue; + let ast = null; + try { + ast = node.getRawAST(); + } catch (e) { + ast = null; + } + if (!ast || !ast.body || ast.body.type !== "BlockStatement") continue; + const shadowed = builder.nativeFunctionNames.indexOf(name) > -1; + const declaredTypes = Boolean(node.hasDeclaredTypes); + const kind = node.isRootKernel ? "root" : node.isSubKernel || shadowed || declaredTypes ? "subKernel" : "helper"; + registerPlanEntry(entries, name, ast, kind, allowedFree); + } + for (const entry of entries.values()) allowedFree.add(entry.name); + for (const entry of entries.values()) analyzePlanEntry(entry, allowedFree); + let effectsChanged = true; + while (effectsChanged) { + effectsChanged = false; + for (const entry of entries.values()) { + if (entry.hasEffects) continue; + for (let i = 0; i < entry.calls.length; i++) { + const callee = entries.get(entry.calls[i]); + if (callee && callee.hasEffects) { + entry.hasEffects = true; + effectsChanged = true; + break; + } + } + } + } + markRecursive(entries); + let changed = true; + while (changed) { + changed = false; + for (const entry of entries.values()) entry.sites = []; + const blocked = new Set; + for (const entry of entries.values()) scanPlanEntry(entries, entry, blocked); + for (const name of blocked) { + const entry = entries.get(name); + if (entry && entry.inlinable) { + entry.inlinable = false; + changed = true; + } + } + if (!changed && applyInlineBudget(entries)) changed = true; + } + const plan = new Map; + for (const entry of entries.values()) { + if (!entry.inlinable) continue; + plan.set(entry.name, { + params: entry.params, + body: entry.body, + assignedParams: entry.assignedParams, + localNames: entry.localNames, + returnsValue: entry.returnsValue + }); + } + for (const entry of entries.values()) if (entry.inlinable && entry.sites.length > 1) { + entry.inlinable = false; + entry.sites = []; + } + return plan; + } + function registerPlanEntry(entries, name, ast, kind, allowedFree) { + if (!entries.has(name)) entries.set(name, { + name: name, + ast: ast, + kind: kind, + params: (ast.params || []).map(param => param.type === "Identifier" ? param.name : null), + body: ast.body.body, + assignedParams: new Set, + localNames: new Set, + returnsValue: false, + inlinable: kind === "helper", + recursive: false, + calls: [], + sites: [], + selfSize: 0, + expandedSize: 0 + }); + const nested = []; + walk(ast.body, node => { + if (node.type === "FunctionDeclaration" && node.id && node.id.name) nested.push(node); + }); + for (let i = 0; i < nested.length; i++) registerPlanEntry(entries, nested[i].id.name, nested[i], "helper", allowedFree); + } + function analyzePlanEntry(entry, allowedFree) { + entry.selfSize = nodeCount(entry.body); + const declared = new Set; + const assigned = new Set; + const free = new Set; + let rejected = false; + let hasEffects = false; + walk(entry.body, node => { + if (node.type === "CallExpression" && node.callee && node.callee.type === "MemberExpression" && node.callee.object && node.callee.object.name === "Math" && node.callee.property && node.callee.property.name === "random") hasEffects = true; + }); + const visit = node => { + if (!node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "LabeledStatement": + rejected = true; + return; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + rejected = true; + return; + + case "VariableDeclarator": + if (node.id && node.id.type === "Identifier") declared.add(node.id.name); + break; + + case "AssignmentExpression": + if (node.left.type === "Identifier") assigned.add(node.left.name); + break; + + case "UpdateExpression": + if (node.argument.type === "Identifier") assigned.add(node.argument.name); + break; + + case "Identifier": + free.add(node.name); + break; + + case "MemberExpression": + visit(node.object); + if (node.computed) visit(node.property); + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child); + } + }; + visit(entry.body); + for (let i = 0; i < entry.params.length; i++) if (entry.params[i] === null) rejected = true; + if (rejected) { + entry.inlinable = false; + return; + } + for (const name of free) { + if (declared.has(name) || entry.params.indexOf(name) > -1 || allowedFree.has(name)) continue; + entry.inlinable = false; + return; + } + entry.localNames = declared; + for (let i = 0; i < entry.params.length; i++) if (assigned.has(entry.params[i])) entry.assignedParams.add(entry.params[i]); + for (const name of assigned) if (!declared.has(name) && entry.params.indexOf(name) === -1) hasEffects = true; + entry.hasEffects = hasEffects; + const reduced = reduceReturns(entry.body); + if (!reduced) { + entry.inlinable = false; + return; + } + entry.returnsValue = reduced.value !== null; + if (entry.selfSize > INLINE_MAX_HELPER_NODES) entry.inlinable = false; + } + function scanPlanEntry(entries, entry, blocked) { + const candidates = name => { + const target = entries.get(name); + return target && target.inlinable && !target.recursive ? target : null; + }; + const hoisted = new Set; + const scan = { + candidates: candidates, + sites: [], + clean: true + }; + const walkStatements = list => { + for (let i = 0; i < list.length; i++) walkStatement(list[i]); + }; + const walkStatement = statement => { + if (!statement || typeof statement.type !== "string") return; + if (statement.type === "FunctionDeclaration") return; + scan.clean = true; + scan.sites = []; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + for (let i = 0; i < scan.sites.length; i++) { + hoisted.add(scan.sites[i].node); + entry.sites.push(scan.sites[i]); + } + switch (statement.type) { + case "BlockStatement": + walkStatements(statement.body); + return; + + case "IfStatement": + walkStatement(statement.consequent); + if (statement.alternate) walkStatement(statement.alternate); + return; + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + walkStatement(statement.body); + return; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) walkStatements(statement.cases[i].consequent); + return; } - return argumentTypes; - } - static getSignature(kernel, argumentTypes) { - throw new Error(`"getSignature" not implemented on ${this.name}`); + }; + walkStatements(entry.body); + walkOwn(entry.body, node => { + if (node.type !== "CallExpression" || hoisted.has(node)) return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) blocked.add(name); + }); + for (let i = 0; i < entry.sites.length; i++) { + const site = entry.sites[i]; + if (site.node.arguments.length < site.entry.params.length) blocked.add(site.entry.name); + for (let j = 0; j < site.node.arguments.length; j++) if (site.node.arguments[j].type === "SpreadElement") blocked.add(site.entry.name); } - functionToIGPUFunction(source, settings = {}) { - if (typeof source !== "string" && typeof source !== "function") throw new Error("source not a string or function"); - const sourceString = typeof source === "string" ? source : source.toString(); - let argumentTypes = []; - if (Array.isArray(settings.argumentTypes)) argumentTypes = settings.argumentTypes; else if (typeof settings.argumentTypes === "object") { - const argumentNames = utils.getArgumentNamesFromString(sourceString); - argumentTypes = argumentNames.map(name => settings.argumentTypes[name]) || []; - const keys = Object.keys(settings.argumentTypes); - if (keys.length > 0 && argumentNames.length > 0 && argumentTypes.every(type => type === void 0)) throw new Error(`argumentTypes keys [${keys.join(", ")}] match none of the function's parameters [${argumentNames.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${keys.map(k => settings.argumentTypes[k]).join("', '")}']`); - } else argumentTypes = settings.argumentTypes || []; - return { - name: settings.name || utils.getFunctionNameFromString(sourceString) || (typeof source === "function" && source.name ? source.name : null), - source: sourceString, - argumentTypes: argumentTypes, - returnType: settings.returnType || null - }; + } + function markRecursive(entries) { + const edges = new Map; + for (const entry of entries.values()) { + const out = new Set; + walkOwn(entry.body, node => { + if (node.type !== "CallExpression") return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) out.add(name); + }); + edges.set(entry.name, out); } - onActivate(previousKernel) {} - switchKernels(reason) { - if (this.switchingKernels) this.switchingKernels.push(reason); else this.switchingKernels = [ reason ]; + const state = new Map; + const onStack = []; + const visit = name => { + if (state.get(name) === "done") return; + if (state.get(name) === "open") { + for (let i = onStack.lastIndexOf(name); i < onStack.length; i++) { + entries.get(onStack[i]).recursive = true; + entries.get(onStack[i]).inlinable = false; + } + return; + } + state.set(name, "open"); + onStack.push(name); + for (const next of edges.get(name) || []) visit(next); + onStack.pop(); + state.set(name, "done"); + }; + for (const name of entries.keys()) visit(name); + } + function applyInlineBudget(entries) { + let bounded = false; + let shed = false; + while (!bounded) { + computeExpandedSizes(entries); + for (const entry of entries.values()) if (entry.inlinable && entry.expandedSize > INLINE_MAX_HELPER_NODES) { + entry.inlinable = false; + shed = true; + } + bounded = true; + let worst = null; + let worstAdded = INLINE_MAX_ADDED_NODES; + for (const entry of entries.values()) { + let added = 0; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) added += callee.expandedSize; + } + if (added > worstAdded) { + worstAdded = added; + worst = entry; + } + } + if (!worst) break; + let victim = null; + for (let i = 0; i < worst.sites.length; i++) { + const callee = entries.get(worst.sites[i].entry.name); + if (!callee || !callee.inlinable) continue; + if (!victim || callee.expandedSize > victim.expandedSize || callee.expandedSize === victim.expandedSize && callee.name < victim.name) victim = callee; + } + if (!victim) break; + victim.inlinable = false; + shed = true; + bounded = false; + } + return shed; + } + function computeExpandedSizes(entries) { + const pending = new Set(entries.keys()); + for (const entry of entries.values()) entry.expandedSize = entry.selfSize; + for (let round = 0; round < pending.size + 1; round++) { + let changed = false; + for (const entry of entries.values()) { + let size = entry.selfSize; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) size += callee.expandedSize; + } + if (size !== entry.expandedSize) { + entry.expandedSize = size; + changed = true; + } + } + if (!changed) break; } - resetSwitchingKernels() { - const existingValue = this.switchingKernels; - this.switchingKernels = null; - return existingValue; + } + function nodeCount(ast) { + let count = 0; + walk(ast, () => { + count++; + }); + return count; + } + function unrollBlock(context, block) { + block.body = unrollList(context, block.body); + } + function unrollList(context, list) { + const result = []; + for (let i = 0; i < list.length; i++) { + const replacement = unrollStatement(context, list[i]); + if (replacement === null) { + result.push(list[i]); + continue; + } + for (let j = 0; j < replacement.length; j++) result.push(replacement[j]); } - checkArgumentTypes(args) { - if (!this.argumentTypes) return; - const length = Math.min(args.length, this.argumentTypes.length); - for (let i = 0; i < length; i++) if (!utils.typeFitsValue(this.argumentTypes[i], args[i])) this.switchKernels({ - type: "argumentTypeMismatch", - index: i, - needed: utils.getVariableType(args[i], this.strictIntegers) - }); + return result; + } + function unrollStatement(context, statement) { + switch (statement.type) { + case "BlockStatement": + unrollBlock(context, statement); + return null; + + case "IfStatement": + statement.consequent = unrollBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = unrollBranch(context, statement.alternate); + return null; + + case "SwitchStatement": + for (let i = 0; i < statement.cases.length; i++) statement.cases[i].consequent = unrollList(context, statement.cases[i].consequent); + return null; + + case "WhileStatement": + case "DoWhileStatement": + statement.body = unrollBranch(context, statement.body); + return null; + + case "ForStatement": + statement.body = unrollBranch(context, statement.body); + return unrollLoop(context, statement); + + default: + return null; } + } + function unrollBranch(context, branch) { + if (!branch) return branch; + if (branch.type === "BlockStatement") { + unrollBlock(context, branch); + return branch; + } + const replacement = unrollStatement(context, branch); + if (replacement === null) return branch; + return stampSynthetic({ + type: "BlockStatement", + body: replacement + }, branch); + } + function unrollLoop(context, loop) { + if (!(context.loopUnrollLimit > 0)) return null; + if (loop.type !== "ForStatement") return null; + const induction = inductionVariable(context, loop); + if (!induction) return null; + const values = tripValues(loop, induction, context.loopUnrollLimit); + if (!values) return null; + if (loop.init && loop.init.type === "VariableDeclaration" && loop.init.declarations[0].init.type !== "Literal") { + const cap = context.functionNode.loopMaxIterations || 1e3; + if (values.length > cap) return null; + } + const body = loop.body ? loop.body.type === "BlockStatement" ? loop.body.body : [ loop.body ] : []; + if (!bodyIsUnrollable(body, induction.name)) return null; + const added = countNodes(body) * (values.length - 1); + if (context.unrollAdded === void 0) context.unrollAdded = 0; + if (context.unrollAdded + added > UNROLL_MAX_ADDED_NODES) return null; + context.unrollAdded += added; + const result = []; + for (let i = 0; i < values.length; i++) result.push(stampSynthetic({ + type: "BlockStatement", + body: cloneNodes(context, body, induction.name, values[i]) + }, loop)); + return result; + } + function countNodes(ast) { + let count = 0; + walk(ast, () => { + count++; + }); + return count; + } + function inductionVariable(context, loop) { + const {init: init} = loop; + if (!init || init.type !== "VariableDeclaration") return null; + if (init.declarations.length !== 1) return null; + const declaration = init.declarations[0]; + if (!declaration.id || declaration.id.type !== "Identifier") return null; + const start = integerLiteral(declaration.init); + if (start === null) return null; + if (init.kind === "var" && nameUsedOutside(context, loop, declaration.id.name)) return null; + return { + name: declaration.id.name, + start: start + }; + } + const comparators = { + "<": (value, bound) => value < bound, + "<=": (value, bound) => value <= bound, + ">": (value, bound) => value > bound, + ">=": (value, bound) => value >= bound, + "!==": (value, bound) => value !== bound, + "!=": (value, bound) => value !== bound }; - function splitArgumentTypes(argumentTypesObject) { - const argumentNames = Object.keys(argumentTypesObject); - const argumentTypes = []; - for (let i = 0; i < argumentNames.length; i++) { - const argumentName = argumentNames[i]; - argumentTypes.push(argumentTypesObject[argumentName]); + function tripValues(loop, induction, limit) { + const {test: test, update: update} = loop; + if (!test || test.type !== "BinaryExpression") return null; + if (!test.left || test.left.type !== "Identifier" || test.left.name !== induction.name) return null; + const bound = integerLiteral(test.right); + if (bound === null) return null; + const compare = comparators[test.operator]; + if (!compare) return null; + const step = inductionStep(update, induction.name); + if (step === null) return null; + const values = []; + let value = induction.start; + while (compare(value, bound)) { + if (values.length >= limit) return null; + values.push(value); + value += step; + } + return values; + } + function inductionStep(update, name) { + if (!update) return null; + if (update.type === "UpdateExpression") { + if (!update.argument || update.argument.type !== "Identifier" || update.argument.name !== name) return null; + return update.operator === "++" ? 1 : update.operator === "--" ? -1 : null; + } + if (update.type !== "AssignmentExpression") return null; + if (!update.left || update.left.type !== "Identifier" || update.left.name !== name) return null; + switch (update.operator) { + case "+=": + { + const step = integerLiteral(update.right); + return step === 0 ? null : step; + } + + case "-=": + { + const step = integerLiteral(update.right); + return step === null || step === 0 ? null : -step; + } + + case "=": + { + const {right: right} = update; + if (!right || right.type !== "BinaryExpression") return null; + const leftIsCounter = right.left.type === "Identifier" && right.left.name === name; + const rightIsCounter = right.right.type === "Identifier" && right.right.name === name; + if (right.operator === "+") { + const step = leftIsCounter ? integerLiteral(right.right) : rightIsCounter ? integerLiteral(right.left) : null; + return step === 0 ? null : step; + } + if (right.operator === "-" && leftIsCounter) { + const step = integerLiteral(right.right); + return step === null || step === 0 ? null : -step; + } + return null; + } + + default: + return null; } - return { - argumentTypes: argumentTypes, - argumentNames: argumentNames + } + function integerLiteral(ast) { + const value = literalNumber(ast); + return value === null || !Number.isInteger(value) ? null : value; + } + function nameUsedOutside(context, loop, name) { + let found = false; + const visit = node => { + if (found || !node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== "string" || node === loop) return; + if (node.type === "Identifier" && node.name === name) { + found = true; + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child); + } + }; + visit(context.ast); + return found; + } + function bodyIsUnrollable(body, name) { + let ok = true; + const reject = () => { + ok = false; + }; + const visit = (node, inBreakable, inContinuable) => { + if (!ok || !node || typeof node !== "object") return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== "string") return; + switch (node.type) { + case "AssignmentExpression": + if (node.left.type === "Identifier" && node.left.name === name) return reject(); + break; + + case "UpdateExpression": + if (node.argument.type === "Identifier" && node.argument.name === name) return reject(); + break; + + case "VariableDeclarator": + if (node.id.type === "Identifier" && node.id.name === name) return reject(); + break; + + case "BreakStatement": + if (node.label || !inBreakable) return reject(); + return; + + case "ContinueStatement": + if (node.label || !inContinuable) return reject(); + return; + + case "LabeledStatement": + return reject(); + + case "CallExpression": + if (isMathRandom(node)) return reject(); + break; + + case "FunctionDeclaration": + case "FunctionExpression": + case "ArrowFunctionExpression": + return reject(); + + case "ForStatement": + case "WhileStatement": + case "DoWhileStatement": + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + + case "SwitchStatement": + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + + case "MemberExpression": + visit(node.object, inBreakable, inContinuable); + if (node.computed) visit(node.property, inBreakable, inContinuable); + return; + } + for (const key in node) { + if (key === "loc" || key === "range" || key === "parent") continue; + const child = node[key]; + if (child && typeof child === "object") visit(child, inBreakable, inContinuable); + } }; + visit(body, false, false); + return ok; + } + function numberNode(value, source) { + const literal = stampSynthetic({ + type: "Literal", + value: Math.abs(value), + raw: `${Math.abs(value)}` + }, source); + if (value >= 0) return literal; + return stampSynthetic({ + type: "UnaryExpression", + operator: "-", + prefix: true, + argument: literal + }, source); + } + function isMathRandom(ast) { + const {callee: callee} = ast; + return Boolean(callee) && callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.object.name === "Math" && callee.property.name === "random"; + } + function cloneNodes(context, nodes, name, value) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneNode(context, nodes[i], name, value); + return result; + } + function cloneNode(context, node, name, value) { + if (!node || typeof node !== "object") return node; + if (Array.isArray(node)) return cloneNodes(context, node, name, value); + if (typeof node.type !== "string") return node; + if (name !== null && node.type === "Identifier" && node.name === name) return numberNode(value, node); + const copy = {}; + const verbatimProperty = node.type === "MemberExpression" && !node.computed; + for (const key in node) { + if (key === "start" || key === "end") continue; + if (key === "loc" || key === "range" || key === "parent") { + copy[key] = node[key]; + continue; + } + copy[key] = cloneNode(context, node[key], verbatimProperty && key === "property" ? null : name, value); + } + return stampSynthetic(copy, node); + } + function threadLocalName(functionNode, name) { + if (!functionNode.localizeThreadCoordinates) return null; + if (functionNode.optimizerDisabled || !functionNode.isRootKernel) return null; + const {output: output} = functionNode; + if (!output || !output.length) return null; + switch (name) { + case "x": + return "x"; + + case "y": + return output.length > 1 ? "y" : "0"; + + case "z": + return output.length > 2 ? "z" : "0"; + + default: + return null; + } } module.exports = { - Kernel: Kernel + optimize: optimize, + buildInlinePlan: buildInlinePlan, + threadLocalName: threadLocalName }; }); var require_function_builder = __commonJSMin((exports, module) => { + const {buildInlinePlan: buildInlinePlan} = require_optimizer(); module.exports = { FunctionBuilder: class FunctionBuilder { static fromKernel(kernel, FunctionNode, extraNodeOptions) { - const {kernelArguments: kernelArguments, kernelConstants: kernelConstants, argumentNames: argumentNames, argumentSizes: argumentSizes, argumentBitRatios: argumentBitRatios, constants: constants, constantBitRatios: constantBitRatios, debug: debug, loopMaxIterations: loopMaxIterations, nativeFunctions: nativeFunctions, output: output, optimizeFloatMemory: optimizeFloatMemory, precision: precision, plugins: plugins, source: source, subKernels: subKernels, functions: functions, leadingReturnStatement: leadingReturnStatement, followingReturnStatement: followingReturnStatement, dynamicArguments: dynamicArguments, dynamicOutput: dynamicOutput} = kernel; + const {kernelArguments: kernelArguments, kernelConstants: kernelConstants, argumentNames: argumentNames, argumentSizes: argumentSizes, argumentBitRatios: argumentBitRatios, constants: constants, constantBitRatios: constantBitRatios, debug: debug, loopMaxIterations: loopMaxIterations, nativeFunctions: nativeFunctions, output: output, optimizeFloatMemory: optimizeFloatMemory, precision: precision, plugins: plugins, source: source, subKernels: subKernels, functions: functions, leadingReturnStatement: leadingReturnStatement, followingReturnStatement: followingReturnStatement, dynamicArguments: dynamicArguments, dynamicOutput: dynamicOutput, loopUnrollLimit: loopUnrollLimit, localizeThreadCoordinates: localizeThreadCoordinates} = kernel; + const optimizerDisabled = Boolean(kernel._optimizerDisabled); + const inliningDisabled = Boolean(kernel._inliningDisabled); const argumentTypes = new Array(kernelArguments.length); const constantTypes = {}; for (let i = 0; i < kernelArguments.length; i++) argumentTypes[i] = kernelArguments[i].type; @@ -5742,6 +7438,7 @@ const onFunctionCall = (functionName, calleeFunctionName, args) => { functionBuilder.trackFunctionCall(functionName, calleeFunctionName, args); }; + const lookupInlineTarget = inliningDisabled ? null : functionName => functionBuilder.lookupInlineTarget(functionName); const onNestedFunction = (ast, source) => { const argumentNames = []; for (let i = 0; i < ast.params.length; i++) argumentNames.push(ast.params[i].name); @@ -5785,7 +7482,11 @@ output: output, plugins: plugins, dynamicArguments: dynamicArguments, - dynamicOutput: dynamicOutput + dynamicOutput: dynamicOutput, + optimizerDisabled: optimizerDisabled, + loopUnrollLimit: loopUnrollLimit, + localizeThreadCoordinates: localizeThreadCoordinates, + lookupInlineTarget: lookupInlineTarget }, extraNodeOptions || {}); const rootNodeOptions = Object.assign({}, nodeOptions, { isRootKernel: true, @@ -5804,6 +7505,7 @@ name: fn.name || void 0, returnType: fn.returnType, argumentTypes: fn.argumentTypes, + hasDeclaredTypes: Boolean(fn.returnType) || (Array.isArray(fn.argumentTypes) ? fn.argumentTypes.some(type => Boolean(type)) : Boolean(fn.argumentTypes && Object.keys(fn.argumentTypes).length > 0)), output: output, plugins: plugins, constants: constants, @@ -5820,7 +7522,11 @@ triggerImplyArgumentType: triggerImplyArgumentType, triggerImplyArgumentBitRatio: triggerImplyArgumentBitRatio, onFunctionCall: onFunctionCall, - onNestedFunction: onNestedFunction + onNestedFunction: onNestedFunction, + optimizerDisabled: optimizerDisabled, + loopUnrollLimit: loopUnrollLimit, + localizeThreadCoordinates: localizeThreadCoordinates, + lookupInlineTarget: lookupInlineTarget })); let subKernelNodes = null; if (subKernels) subKernelNodes = subKernels.map(subKernel => { @@ -5852,6 +7558,7 @@ this.lookupChain = []; this.functionNodeDependencies = {}; this.functionCalls = {}; + this._inlinePlan = null; if (this.rootNode) this.functionMap["kernel"] = this.rootNode; if (this.functionNodes) for (let i = 0; i < this.functionNodes.length; i++) this.functionMap[this.functionNodes[i].name] = this.functionNodes[i]; if (this.subKernelNodes) for (let i = 0; i < this.subKernelNodes.length; i++) this.functionMap[this.subKernelNodes[i].name] = this.subKernelNodes[i]; @@ -5860,6 +7567,10 @@ this.nativeFunctionNames.push(nativeFunction.name); } } + lookupInlineTarget(functionName) { + if (!this._inlinePlan) this._inlinePlan = buildInlinePlan(this); + return this._inlinePlan.get(functionName) || null; + } addFunctionNode(functionNode) { if (!functionNode.name) throw new Error("functionNode.name needs set"); this.functionMap[functionNode.name] = functionNode; @@ -6352,6 +8063,7 @@ const acorn = require_acorn(); const {utils: utils} = require_utils(); const {FunctionTracer: FunctionTracer} = require_function_tracer(); + const {optimize: optimize} = require_optimizer(); const mathProperties = [ "E", "PI", "SQRT2", "SQRT1_2", "LN2", "LN10", "LOG2E", "LOG10E" ]; const mathFunctions = [ "abs", "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", "cbrt", "ceil", "clz32", "cos", "cosh", "expm1", "exp", "floor", "fround", "imul", "log", "log2", "log10", "log1p", "max", "min", "pow", "random", "round", "sign", "sin", "sinh", "sqrt", "tan", "tanh", "trunc" ]; const allowedExpressions = [ "value", "value[]", "value[][]", "value[][][]", "value[][][][]", "value.value", "value.thread.value", "this.thread.value", "this.output.value", "this.constants.value", "this.constants.value[]", "this.constants.value[][]", "this.constants.value[][][]", "this.constants.value[][][][]", "fn()[]", "fn()[][]", "fn()[][][]", "[][]" ]; @@ -6399,6 +8111,11 @@ this.dynamicArguments = null; this.strictTypingChecking = false; this.fixIntegerDivisionAccuracy = null; + this.optimizerDisabled = false; + this.loopUnrollLimit = 8; + this.lookupInlineTarget = null; + this.hasDeclaredTypes = false; + this.localizeThreadCoordinates = false; if (settings) for (const p in settings) { if (!settings.hasOwnProperty(p)) continue; if (!this.hasOwnProperty(p)) continue; @@ -6406,6 +8123,7 @@ } this.literalTypes = {}; this.validate(); + this._rawAST = null; this._string = null; this._internalVariableNames = {}; } @@ -6453,25 +8171,46 @@ get requiresSequenceFreeForInit() { return false; } - getJsAST(inParser) { - if (this.ast) return this.ast; + get readsCanFault() { + return false; + } + get readsFaultAtOneLevel() { + return false; + } + getRawAST(inParser) { + if (this._rawAST) return this._rawAST; if (typeof this.source === "object") { normalizeMinifiedStatements(this.source, this.requiresSequenceFreeForInit); - this.traceFunctionAST(this.source); - return this.ast = this.source; + return this._rawAST = this.source; } inParser = inParser || acorn; if (inParser === null) throw new Error("Missing JS to AST parser"); - const ast = Object.freeze(inParser.parse(`const parser_${this.name} = ${this.source};`, { + const functionAST = Object.freeze(inParser.parse(`const parser_${this.name} = ${this.source};`, { locations: true, ecmaVersion: 2020 - })); - const functionAST = ast.body[0].declarations[0].init; + })).body[0].declarations[0].init; normalizeMinifiedStatements(functionAST, this.requiresSequenceFreeForInit); + return this._rawAST = functionAST; + } + getJsAST(inParser) { + if (this.ast) return this.ast; + const functionAST = this.getRawAST(inParser); + try { + this.optimizeAST(functionAST); + } catch (e) { + if (e && typeof e === "object") e.isOptimizerFailure = true; + throw e; + } this.traceFunctionAST(functionAST); - if (!ast) throw new Error("Failed to parse JS code"); return this.ast = functionAST; } + optimizeAST(ast) { + if (this.optimizerDisabled) return ast; + return optimize(this, ast, { + loopUnrollLimit: this.loopUnrollLimit, + lookupInlineTarget: this.lookupInlineTarget + }); + } getAssignedArguments() { if (this._assignedArguments) return this._assignedArguments; const assigned = new Set; @@ -7171,8 +8910,11 @@ astUnaryExpression(uNode, retArr) { if (this.checkAndUpconvertBitwiseUnary(uNode, retArr)) return retArr; if (uNode.prefix) { + const collides = uNode.operator === "-" || uNode.operator === "+"; + if (collides) retArr.push("("); retArr.push(uNode.operator); this.astGeneric(uNode.argument, retArr); + if (collides) retArr.push(")"); } else { this.astGeneric(uNode.argument, retArr); retArr.push(uNode.operator); @@ -7663,7 +9405,11 @@ }); var require_function_node$4 = __commonJSMin((exports, module) => { const {FunctionNode: FunctionNode} = require_function_node$5(); + const {threadLocalName: threadLocalName} = require_optimizer(); var CPUFunctionNode = class extends FunctionNode { + get readsCanFault() { + return true; + } markupUserName(name) { if (this.isRootKernel && this.getAssignedArguments().has(name)) return `cellShadow_user_${name}`; return `user_${name}`; @@ -7886,8 +9632,11 @@ const {signature: signature, type: type, property: property, xProperty: xProperty, yProperty: yProperty, zProperty: zProperty, name: name, origin: origin} = this.getMemberExpressionDetails(mNode); switch (signature) { case "this.thread.value": - retArr.push(`_this.thread.${name}`); - return retArr; + { + const local = threadLocalName(this, name); + retArr.push(local === null ? `_this.thread.${name}` : local); + return retArr; + } case "this.output.value": switch (name) { @@ -8238,6 +9987,7 @@ } constructor(source, settings) { super(source, settings); + this._inliningDisabled = true; this.mergeSettings(source.settings || settings); this._imageData = null; this._colorData = null; @@ -8293,7 +10043,7 @@ this.setupConstants(); this.setupArguments(arguments); this.validateSettings(arguments); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); if (this.graphical) { const {canvas: canvas, output: output} = this; if (!canvas) throw new Error("no canvas available for using graphical output"); @@ -9977,7 +11727,7 @@ astBinaryExpression(ast, retArr) { if (this.checkAndUpconvertOperator(ast, retArr)) return retArr; if (ast.operator === "/") { - const wrap = this.fixIntegerDivisionAccuracy; + const wrap = this.fixIntegerDivisionAccuracy && !this.divisionIsProvablyFractional(ast); retArr.push(wrap ? "divWithIntCheck(" : "("); this.pushState("building-float"); switch (this.getType(ast.left)) { @@ -10150,6 +11900,9 @@ retArr.push(")"); return retArr; } + divisionIsProvablyFractional(ast) { + return isFractionalLiteral(ast.left) || isFractionalLiteral(ast.right); + } checkAndUpconvertOperator(ast, retArr) { const bitwiseResult = this.checkAndUpconvertBitwiseOperators(ast, retArr); if (bitwiseResult) return bitwiseResult; @@ -11108,7 +12861,8 @@ astSwitchStatement(ast, retArr) { if (ast.type !== "SwitchStatement") throw this.astErrorOutput("Invalid switch statement", ast); const {discriminant: discriminant, cases: cases} = ast; - const type = this.getType(discriminant); + const literalDiscriminant = this.getType(discriminant) === "LiteralInteger"; + const type = literalDiscriminant ? "Integer" : this.getType(discriminant); const varName = `switchDiscriminant${this.astKey(ast, "_")}`; switch (type) { case "Float": @@ -11120,7 +12874,7 @@ case "Integer": retArr.push(`int ${varName} = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) this.castLiteralToInteger(discriminant, retArr); else this.astGeneric(discriminant, retArr); retArr.push(";\n"); break; } @@ -11529,7 +13283,9 @@ retArr.push(")"); continue; } else if (targetType === "Integer") { + this.pushState("building-integer"); this.astGeneric(argument, retArr); + this.popState("building-integer"); continue; } break; @@ -11625,6 +13381,12 @@ this.castLiteralToInteger(property, result); break; + case "Integer": + this.pushState("building-integer"); + this.astGeneric(property, result); + this.popState("building-integer"); + break; + default: this.astGeneric(property, result); } @@ -11766,6 +13528,11 @@ "===": "==", "!==": "!=" }; + function isFractionalLiteral(ast) { + if (!ast) return false; + if (ast.type === "UnaryExpression" && (ast.operator === "-" || ast.operator === "+")) return isFractionalLiteral(ast.argument); + return ast.type === "Literal" && typeof ast.value === "number" && !Number.isInteger(ast.value); + } module.exports = { WebGLFunctionNode: WebGLFunctionNode }; @@ -13614,13 +15381,23 @@ }; return this.canvas.getContext("webgl", settings) || this.canvas.getContext("experimental-webgl", settings); } + pluginMatchSource() { + if (typeof this.source !== "string") return null; + if (!this.functions || this.functions.length < 1) return this.source; + const sources = [ this.source ]; + for (let i = 0; i < this.functions.length; i++) { + const source = this.functions[i] ? this.functions[i].source : null; + if (typeof source === "string") sources.push(source); + } + return sources.join("\n"); + } initPlugins(settings) { const pluginsToUse = []; - const {source: source} = this; + const source = this.pluginMatchSource(); if (typeof source === "string") for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; if (source.match(plugin.functionMatch)) pluginsToUse.push(plugin); - } else if (typeof source === "object") { + } else if (typeof this.source === "object") { if (settings.pluginNames) for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; if (settings.pluginNames.some(pluginName => pluginName === plugin.name)) pluginsToUse.push(plugin); @@ -13805,7 +15582,7 @@ this.setupArguments(arguments); if (this.fallbackRequested) return; this.updateMaxTexSize(); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); const failureResult = this.pickRenderStrategy(arguments); if (failureResult) return failureResult; const {texSize: texSize, context: gl, canvas: canvas} = this; @@ -14148,7 +15925,9 @@ } _getPluginsString() { if (!this.plugins) return "\n"; - return this.plugins.map(plugin => plugin.source && this.source.match(plugin.functionMatch) ? plugin.source : "").join("\n"); + const source = this.pluginMatchSource(); + if (typeof source !== "string") return "\n"; + return this.plugins.map(plugin => plugin.source && source.match(plugin.functionMatch) ? plugin.source : "").join("\n"); } _getConstantsString() { const result = []; @@ -16472,7 +18251,8 @@ astSwitchStatement(ast, retArr) { if (ast.type !== "SwitchStatement") throw this.astErrorOutput("Invalid switch statement", ast); const {discriminant: discriminant, cases: cases} = ast; - const type = this.getType(discriminant); + const literalDiscriminant = this.getType(discriminant) === "LiteralInteger"; + const type = literalDiscriminant ? "Integer" : this.getType(discriminant); const varName = `switchDiscriminant${this.astKey(ast, "_")}`; switch (type) { case "Float": @@ -16484,7 +18264,7 @@ case "Integer": retArr.push(`var ${varName} : i32 = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) this.castLiteralToInteger(discriminant, retArr); else this.astGeneric(discriminant, retArr); retArr.push(";\n"); break; @@ -16802,7 +18582,9 @@ retArr.push(")"); continue; } else if (targetType === "Integer") { + this.pushState("building-integer"); this.astGeneric(argument, retArr); + this.popState("building-integer"); continue; } break; @@ -17188,9 +18970,11 @@ this.validateSettings(arguments); const threadDim = this.threadDim = Array.from(this.output); while (threadDim.length < 3) threadDim.push(1); - this.translateSource(); - this.paramsLayout = this.computeParamsLayout(); - this.compiledSource = this.assembleWGSL(); + this.buildWithOptimizer(() => { + this.translateSource(); + this.paramsLayout = this.computeParamsLayout(); + this.compiledSource = this.assembleWGSL(); + }); if (this.debug) { console.log("WGSL Shader Output:"); console.log(this.compiledSource); @@ -18634,6 +20418,12 @@ } } var WebAssemblyFunctionNode = class extends FunctionNode { + get readsCanFault() { + return true; + } + get readsFaultAtOneLevel() { + return true; + } constructor(source, settings) { super(source, settings); this.assembler = null; @@ -19369,6 +21159,13 @@ this.em.localSet(dLocal); break; + case "LiteralInteger": + dIsInt = true; + dLocal = this.em.addLocal("i32"); + this.castLiteralToInteger(discriminant); + this.em.localSet(dLocal); + break; + default: throw this.astErrorOutput(`Unhandled switch discriminant type "${type}"`, ast); } @@ -21430,6 +23227,13 @@ em.localSet(dLocal); break; + case "LiteralInteger": + dIsInt = true; + dLocal = em.addLocal("i32"); + this.castLiteralToInteger(discriminant); + em.localSet(dLocal); + break; + default: throw this.astErrorOutput(`Unhandled switch discriminant type "${type}"`, ast); } @@ -21473,6 +23277,7 @@ break; case "Integer": + case "LiteralInteger": dIsInt = true; dLocal = em.addLocal("v128"); this.vCoerce(this.vexpr(discriminant), "vi32"); @@ -22738,9 +24543,17 @@ this.validateSettings(arguments); const threadDim = this.threadDim = Array.from(this.output); while (threadDim.length < 3) threadDim.push(1); - if (!this.translateSource()) return this.requestFallback(arguments, `return type ${this.returnType} is not supported on the webasm backend`); - this.buildSignature(arguments); - this._instantiate(this._entryKey(arguments), arguments); + let unsupportedReturnType = false; + this.buildWithOptimizer(() => { + if (!this.translateSource()) { + unsupportedReturnType = true; + return; + } + unsupportedReturnType = false; + this.buildSignature(arguments); + this._instantiate(this._entryKey(arguments), arguments); + }); + if (unsupportedReturnType) return this.requestFallback(arguments, `return type ${this.returnType} is not supported on the webasm backend`); this.built = true; } validateSettings(args) { @@ -24740,7 +26553,7 @@ immutable: true, dynamicArguments: true }, overrides || {}); - const optional = [ "constants", "constantTypes", "precision", "loopMaxIterations", "strictIntegers", "fixIntegerDivisionAccuracy", "optimizeFloatMemory", "tactic", "functions", "nativeFunctions", "injectedNative", "debug", "randomSeed", "returnType" ]; + const optional = [ "constants", "constantTypes", "precision", "loopMaxIterations", "strictIntegers", "fixIntegerDivisionAccuracy", "optimizeFloatMemory", "tactic", "functions", "nativeFunctions", "injectedNative", "debug", "randomSeed", "returnType", "loopUnrollLimit", "_optimizerDisabled", "_inliningDisabled" ]; if (kernel.declaredArgumentTypes) settings.argumentTypes = kernel.declaredArgumentTypes.slice(); for (let i = 0; i < optional.length; i++) { const name = optional[i]; @@ -25197,6 +27010,8 @@ injectedNative: kernelRun.injectedNative, subKernels: kernelRun.subKernels, strictIntegers: kernelRun.strictIntegers, + _optimizerDisabled: kernelRun._optimizerDisabled, + loopUnrollLimit: kernelRun.loopUnrollLimit, randomSeed: kernelRun.randomSeed, debug: kernelRun.debug, asyncMode: kernelRun.asyncMode, @@ -25249,6 +27064,8 @@ injectedNative: _kernel.injectedNative, subKernels: _kernel.subKernels, strictIntegers: _kernel.strictIntegers, + _optimizerDisabled: _kernel._optimizerDisabled, + loopUnrollLimit: _kernel.loopUnrollLimit, randomSeed: _kernel.randomSeed, debug: _kernel.debug, asyncMode: _kernel.asyncMode, @@ -25326,6 +27143,8 @@ precision: currentKernel.precision, tactic: currentKernel.tactic, strictIntegers: currentKernel.strictIntegers, + _optimizerDisabled: currentKernel._optimizerDisabled, + loopUnrollLimit: currentKernel.loopUnrollLimit, fixIntegerDivisionAccuracy: currentKernel.fixIntegerDivisionAccuracy, subKernels: currentKernel.subKernels, graphical: currentKernel.graphical, diff --git a/dist/gpu-browser.min.js b/dist/gpu-browser.min.js index 83d3e66f..19a84407 100644 --- a/dist/gpu-browser.min.js +++ b/dist/gpu-browser.min.js @@ -5,11 +5,11 @@ * GPU Accelerated JavaScript * * @version 2.23.0 - * @date Mon Aug 03 2026 18:12:01 GMT+0800 (Singapore Standard Time) + * @date Wed Aug 05 2026 10:06:18 GMT+0800 (Singapore Standard Time) * * @license MIT * The MIT License * * Copyright (c) 2026 gpu.js Team */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):(e="undefined"!=typeof globalThis?globalThis:e||self).GPU=t()}(this,function(){var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),t=e((e,t)=>{function s(e){const t=new Array(e.length);for(let s=0;s{e.output=l(t),e.graphical&&u(e)},e.toJSON=()=>{throw new Error("Not usable with gpuMock")},e.setConstants=t=>(e.constants=t,e),e.setGraphical=t=>(e.graphical=t,e),e.setCanvas=t=>(e.canvas=t,e),e.setContext=t=>(e.context=t,e),e.destroy=()=>{},e.validateSettings=()=>{},e.graphical&&e.output&&u(e),e.exec=function(){return new Promise((t,s)=>{try{t(e.apply(e,arguments))}catch(e){s(e)}})},e.getPixels=t=>{const{x:s,y:r}=e.output;return t?function(e,t,s){const r=s/2|0,n=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee,s=["setWarnVarUsage","setArgumentTypes","setTactic","setOptimizeFloatMemory","setDebug","setLoopMaxIterations","setConstantTypes","setFunctions","setNativeFunctions","setInjectedNative","setPipeline","setPrecision","setOutputToTexture","setImmutable","setStrictIntegers","setDynamicOutput","setHardcodeConstants","setDynamicArguments","setUseLegacyEncoder","setWarnVarUsage","addSubKernel"];for(let r=0;r{var s,r;s=e,r=function(e){"use strict";var t=[509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,7,9,32,4,318,1,80,3,71,10,50,3,123,2,54,14,32,10,3,1,11,3,46,10,8,0,46,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,3,0,158,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,68,8,2,0,3,0,2,3,2,4,2,0,15,1,83,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,7,19,58,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,343,9,54,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,10,1,2,0,49,6,4,4,14,10,5350,0,7,14,11465,27,2343,9,87,9,39,4,60,6,26,9,535,9,470,0,2,54,8,3,82,0,12,1,19628,1,4178,9,519,45,3,22,543,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,101,0,161,6,10,9,357,0,62,13,499,13,245,1,2,9,726,6,110,6,6,9,4759,9,787719,239],s=[0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,13,10,2,14,2,6,2,1,2,10,2,14,2,6,2,1,4,51,13,310,10,21,11,7,25,5,2,41,2,8,70,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,39,27,10,22,251,41,7,1,17,2,60,28,11,0,9,21,43,17,47,20,28,22,13,52,58,1,3,0,14,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,20,1,64,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,31,9,2,0,3,0,2,37,2,0,26,0,2,0,45,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,38,6,186,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,19,72,200,32,32,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,16,0,2,12,2,33,125,0,80,921,103,110,18,195,2637,96,16,1071,18,5,26,3994,6,582,6842,29,1763,568,8,30,18,78,18,29,19,47,17,3,32,20,6,18,433,44,212,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,42,9,8936,3,2,6,2,1,2,290,16,0,30,2,3,0,15,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,1845,30,7,5,262,61,147,44,11,6,17,0,322,29,19,43,485,27,229,29,3,0,496,6,2,3,2,1,2,14,2,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42719,33,4153,7,221,3,5761,15,7472,16,621,2467,541,1507,4938,6,4191],r="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",n={3:"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",5:"class enum extends super const export import",6:"enum",strict:"implements interface let package private protected public static yield",strictBind:"eval arguments"},i="break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this",a={5:i,"5module":i+" export import",6:i+" const class extends export import super"},o=/^in(stanceof)?$/,u=new RegExp("["+r+"]"),l=new RegExp("["+r+"\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65]");function h(e,t){for(var s=65536,r=0;re)return!1;if((s+=t[r+1])>=e)return!0}return!1}function c(e,t){return e<65?36===e:e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&u.test(String.fromCharCode(e)):!1!==t&&h(e,s)))}function p(e,r){return e<48?36===e:e<58||!(e<65)&&(e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&l.test(String.fromCharCode(e)):!1!==r&&(h(e,s)||h(e,t)))))}var d=function(e,t){void 0===t&&(t={}),this.label=e,this.keyword=t.keyword,this.beforeExpr=!!t.beforeExpr,this.startsExpr=!!t.startsExpr,this.isLoop=!!t.isLoop,this.isAssign=!!t.isAssign,this.prefix=!!t.prefix,this.postfix=!!t.postfix,this.binop=t.binop||null,this.updateContext=null};function f(e,t){return new d(e,{beforeExpr:!0,binop:t})}var m={beforeExpr:!0},g={startsExpr:!0},y={};function x(e,t){return void 0===t&&(t={}),t.keyword=e,y[e]=new d(e,t)}var b={num:new d("num",g),regexp:new d("regexp",g),string:new d("string",g),name:new d("name",g),privateId:new d("privateId",g),eof:new d("eof"),bracketL:new d("[",{beforeExpr:!0,startsExpr:!0}),bracketR:new d("]"),braceL:new d("{",{beforeExpr:!0,startsExpr:!0}),braceR:new d("}"),parenL:new d("(",{beforeExpr:!0,startsExpr:!0}),parenR:new d(")"),comma:new d(",",m),semi:new d(";",m),colon:new d(":",m),dot:new d("."),question:new d("?",m),questionDot:new d("?."),arrow:new d("=>",m),template:new d("template"),invalidTemplate:new d("invalidTemplate"),ellipsis:new d("...",m),backQuote:new d("`",g),dollarBraceL:new d("${",{beforeExpr:!0,startsExpr:!0}),eq:new d("=",{beforeExpr:!0,isAssign:!0}),assign:new d("_=",{beforeExpr:!0,isAssign:!0}),incDec:new d("++/--",{prefix:!0,postfix:!0,startsExpr:!0}),prefix:new d("!/~",{beforeExpr:!0,prefix:!0,startsExpr:!0}),logicalOR:f("||",1),logicalAND:f("&&",2),bitwiseOR:f("|",3),bitwiseXOR:f("^",4),bitwiseAND:f("&",5),equality:f("==/!=/===/!==",6),relational:f("/<=/>=",7),bitShift:f("<>/>>>",8),plusMin:new d("+/-",{beforeExpr:!0,binop:9,prefix:!0,startsExpr:!0}),modulo:f("%",10),star:f("*",10),slash:f("/",10),starstar:new d("**",{beforeExpr:!0}),coalesce:f("??",1),_break:x("break"),_case:x("case",m),_catch:x("catch"),_continue:x("continue"),_debugger:x("debugger"),_default:x("default",m),_do:x("do",{isLoop:!0,beforeExpr:!0}),_else:x("else",m),_finally:x("finally"),_for:x("for",{isLoop:!0}),_function:x("function",g),_if:x("if"),_return:x("return",m),_switch:x("switch"),_throw:x("throw",m),_try:x("try"),_var:x("var"),_const:x("const"),_while:x("while",{isLoop:!0}),_with:x("with"),_new:x("new",{beforeExpr:!0,startsExpr:!0}),_this:x("this",g),_super:x("super",g),_class:x("class",g),_extends:x("extends",m),_export:x("export"),_import:x("import",g),_null:x("null",g),_true:x("true",g),_false:x("false",g),_in:x("in",{beforeExpr:!0,binop:7}),_instanceof:x("instanceof",{beforeExpr:!0,binop:7}),_typeof:x("typeof",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_void:x("void",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_delete:x("delete",{beforeExpr:!0,prefix:!0,startsExpr:!0})},v=/\r\n?|\n|\u2028|\u2029/,S=new RegExp(v.source,"g");function T(e){return 10===e||13===e||8232===e||8233===e}function A(e,t,s){void 0===s&&(s=e.length);for(var r=t;r>10),56320+(1023&e)))}var R=/(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/,N=function(e,t){this.line=e,this.column=t};N.prototype.offset=function(e){return new N(this.line,this.column+e)};var M=function(e,t,s){this.start=t,this.end=s,null!==e.sourceFile&&(this.source=e.sourceFile)};function G(e,t){for(var s=1,r=0;;){var n=A(e,r,t);if(n<0)return new N(s,t-r);++s,r=n}}var O={ecmaVersion:null,sourceType:"script",onInsertedSemicolon:null,onTrailingComma:null,allowReserved:null,allowReturnOutsideFunction:!1,allowImportExportEverywhere:!1,allowAwaitOutsideFunction:null,allowSuperOutsideMethod:null,allowHashBang:!1,checkPrivateFields:!0,locations:!1,onToken:null,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null,preserveParens:!1},V=!1;function P(e){var t={};for(var s in O)t[s]=e&&C(e,s)?e[s]:O[s];if("latest"===t.ecmaVersion?t.ecmaVersion=1e8:null==t.ecmaVersion?(!V&&"object"==typeof console&&console.warn&&(V=!0,console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.")),t.ecmaVersion=11):t.ecmaVersion>=2015&&(t.ecmaVersion-=2009),null==t.allowReserved&&(t.allowReserved=t.ecmaVersion<5),e&&null!=e.allowHashBang||(t.allowHashBang=t.ecmaVersion>=14),L(t.onToken)){var r=t.onToken;t.onToken=function(e){return r.push(e)}}return L(t.onComment)&&(t.onComment=function(e,t){return function(s,r,n,i,a,o){var u={type:s?"Block":"Line",value:r,start:n,end:i};e.locations&&(u.loc=new M(this,a,o)),e.ranges&&(u.range=[n,i]),t.push(u)}}(t,t.onComment)),t}var B=256;function z(e,t){return 2|(e?4:0)|(t?8:0)}var U=function(e,t,s){this.options=e=P(e),this.sourceFile=e.sourceFile,this.keywords=F(a[e.ecmaVersion>=6?6:"module"===e.sourceType?"5module":5]);var r="";!0!==e.allowReserved&&(r=n[e.ecmaVersion>=6?6:5===e.ecmaVersion?5:3],"module"===e.sourceType&&(r+=" await")),this.reservedWords=F(r);var i=(r?r+" ":"")+n.strict;this.reservedWordsStrict=F(i),this.reservedWordsStrictBind=F(i+" "+n.strictBind),this.input=String(t),this.containsEsc=!1,s?(this.pos=s,this.lineStart=this.input.lastIndexOf("\n",s-1)+1,this.curLine=this.input.slice(0,this.lineStart).split(v).length):(this.pos=this.lineStart=0,this.curLine=1),this.type=b.eof,this.value=null,this.start=this.end=this.pos,this.startLoc=this.endLoc=this.curPosition(),this.lastTokEndLoc=this.lastTokStartLoc=null,this.lastTokStart=this.lastTokEnd=this.pos,this.context=this.initialContext(),this.exprAllowed=!0,this.inModule="module"===e.sourceType,this.strict=this.inModule||this.strictDirective(this.pos),this.potentialArrowAt=-1,this.potentialArrowInForAwait=!1,this.yieldPos=this.awaitPos=this.awaitIdentPos=0,this.labels=[],this.undefinedExports=Object.create(null),0===this.pos&&e.allowHashBang&&"#!"===this.input.slice(0,2)&&this.skipLineComment(2),this.scopeStack=[],this.enterScope(1),this.regexpState=null,this.privateNameStack=[]},K={inFunction:{configurable:!0},inGenerator:{configurable:!0},inAsync:{configurable:!0},canAwait:{configurable:!0},allowSuper:{configurable:!0},allowDirectSuper:{configurable:!0},treatFunctionsAsVar:{configurable:!0},allowNewDotTarget:{configurable:!0},inClassStaticBlock:{configurable:!0}};U.prototype.parse=function(){var e=this.options.program||this.startNode();return this.nextToken(),this.parseTopLevel(e)},K.inFunction.get=function(){return(2&this.currentVarScope().flags)>0},K.inGenerator.get=function(){return(8&this.currentVarScope().flags)>0&&!this.currentVarScope().inClassFieldInit},K.inAsync.get=function(){return(4&this.currentVarScope().flags)>0&&!this.currentVarScope().inClassFieldInit},K.canAwait.get=function(){for(var e=this.scopeStack.length-1;e>=0;e--){var t=this.scopeStack[e];if(t.inClassFieldInit||t.flags&B)return!1;if(2&t.flags)return(4&t.flags)>0}return this.inModule&&this.options.ecmaVersion>=13||this.options.allowAwaitOutsideFunction},K.allowSuper.get=function(){var e=this.currentThisScope(),t=e.flags,s=e.inClassFieldInit;return(64&t)>0||s||this.options.allowSuperOutsideMethod},K.allowDirectSuper.get=function(){return(128&this.currentThisScope().flags)>0},K.treatFunctionsAsVar.get=function(){return this.treatFunctionsAsVarInScope(this.currentScope())},K.allowNewDotTarget.get=function(){var e=this.currentThisScope(),t=e.flags,s=e.inClassFieldInit;return(258&t)>0||s},K.inClassStaticBlock.get=function(){return(this.currentVarScope().flags&B)>0},U.extend=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];for(var s=this,r=0;r=,?^&]/.test(n)||"!"===n&&"="===this.input.charAt(r+1))}e+=t[0].length,_.lastIndex=e,e+=_.exec(this.input)[0].length,";"===this.input[e]&&e++}},W.eat=function(e){return this.type===e&&(this.next(),!0)},W.isContextual=function(e){return this.type===b.name&&this.value===e&&!this.containsEsc},W.eatContextual=function(e){return!!this.isContextual(e)&&(this.next(),!0)},W.expectContextual=function(e){this.eatContextual(e)||this.unexpected()},W.canInsertSemicolon=function(){return this.type===b.eof||this.type===b.braceR||v.test(this.input.slice(this.lastTokEnd,this.start))},W.insertSemicolon=function(){if(this.canInsertSemicolon())return this.options.onInsertedSemicolon&&this.options.onInsertedSemicolon(this.lastTokEnd,this.lastTokEndLoc),!0},W.semicolon=function(){this.eat(b.semi)||this.insertSemicolon()||this.unexpected()},W.afterTrailingComma=function(e,t){if(this.type===e)return this.options.onTrailingComma&&this.options.onTrailingComma(this.lastTokStart,this.lastTokStartLoc),t||this.next(),!0},W.expect=function(e){this.eat(e)||this.unexpected()},W.unexpected=function(e){this.raise(null!=e?e:this.start,"Unexpected token")};var q=function(){this.shorthandAssign=this.trailingComma=this.parenthesizedAssign=this.parenthesizedBind=this.doubleProto=-1};W.checkPatternErrors=function(e,t){if(e){e.trailingComma>-1&&this.raiseRecoverable(e.trailingComma,"Comma is not permitted after the rest element");var s=t?e.parenthesizedAssign:e.parenthesizedBind;s>-1&&this.raiseRecoverable(s,t?"Assigning to rvalue":"Parenthesized pattern")}},W.checkExpressionErrors=function(e,t){if(!e)return!1;var s=e.shorthandAssign,r=e.doubleProto;if(!t)return s>=0||r>=0;s>=0&&this.raise(s,"Shorthand property assignments are valid only in destructuring patterns"),r>=0&&this.raiseRecoverable(r,"Redefinition of __proto__ property")},W.checkYieldAwaitInDefaultParams=function(){this.yieldPos&&(!this.awaitPos||this.yieldPos55295&&r<56320)return!0;if(c(r,!0)){for(var n=s+1;p(r=this.input.charCodeAt(n),!0);)++n;if(92===r||r>55295&&r<56320)return!0;var i=this.input.slice(s,n);if(!o.test(i))return!0}return!1},X.isAsyncFunction=function(){if(this.options.ecmaVersion<8||!this.isContextual("async"))return!1;_.lastIndex=this.pos;var e,t=_.exec(this.input),s=this.pos+t[0].length;return!(v.test(this.input.slice(this.pos,s))||"function"!==this.input.slice(s,s+8)||s+8!==this.input.length&&(p(e=this.input.charCodeAt(s+8))||e>55295&&e<56320))},X.parseStatement=function(e,t,s){var r,n=this.type,i=this.startNode();switch(this.isLet(e)&&(n=b._var,r="let"),n){case b._break:case b._continue:return this.parseBreakContinueStatement(i,n.keyword);case b._debugger:return this.parseDebuggerStatement(i);case b._do:return this.parseDoStatement(i);case b._for:return this.parseForStatement(i);case b._function:return e&&(this.strict||"if"!==e&&"label"!==e)&&this.options.ecmaVersion>=6&&this.unexpected(),this.parseFunctionStatement(i,!1,!e);case b._class:return e&&this.unexpected(),this.parseClass(i,!0);case b._if:return this.parseIfStatement(i);case b._return:return this.parseReturnStatement(i);case b._switch:return this.parseSwitchStatement(i);case b._throw:return this.parseThrowStatement(i);case b._try:return this.parseTryStatement(i);case b._const:case b._var:return r=r||this.value,e&&"var"!==r&&this.unexpected(),this.parseVarStatement(i,r);case b._while:return this.parseWhileStatement(i);case b._with:return this.parseWithStatement(i);case b.braceL:return this.parseBlock(!0,i);case b.semi:return this.parseEmptyStatement(i);case b._export:case b._import:if(this.options.ecmaVersion>10&&n===b._import){_.lastIndex=this.pos;var a=_.exec(this.input),o=this.pos+a[0].length,u=this.input.charCodeAt(o);if(40===u||46===u)return this.parseExpressionStatement(i,this.parseExpression())}return this.options.allowImportExportEverywhere||(t||this.raise(this.start,"'import' and 'export' may only appear at the top level"),this.inModule||this.raise(this.start,"'import' and 'export' may appear only with 'sourceType: module'")),n===b._import?this.parseImport(i):this.parseExport(i,s);default:if(this.isAsyncFunction())return e&&this.unexpected(),this.next(),this.parseFunctionStatement(i,!0,!e);var l=this.value,h=this.parseExpression();return n===b.name&&"Identifier"===h.type&&this.eat(b.colon)?this.parseLabeledStatement(i,l,h,e):this.parseExpressionStatement(i,h)}},X.parseBreakContinueStatement=function(e,t){var s="break"===t;this.next(),this.eat(b.semi)||this.insertSemicolon()?e.label=null:this.type!==b.name?this.unexpected():(e.label=this.parseIdent(),this.semicolon());for(var r=0;r=6?this.eat(b.semi):this.semicolon(),this.finishNode(e,"DoWhileStatement")},X.parseForStatement=function(e){this.next();var t=this.options.ecmaVersion>=9&&this.canAwait&&this.eatContextual("await")?this.lastTokStart:-1;if(this.labels.push(H),this.enterScope(0),this.expect(b.parenL),this.type===b.semi)return t>-1&&this.unexpected(t),this.parseFor(e,null);var s=this.isLet();if(this.type===b._var||this.type===b._const||s){var r=this.startNode(),n=s?"let":this.value;return this.next(),this.parseVar(r,!0,n),this.finishNode(r,"VariableDeclaration"),(this.type===b._in||this.options.ecmaVersion>=6&&this.isContextual("of"))&&1===r.declarations.length?(this.options.ecmaVersion>=9&&(this.type===b._in?t>-1&&this.unexpected(t):e.await=t>-1),this.parseForIn(e,r)):(t>-1&&this.unexpected(t),this.parseFor(e,r))}var i=this.isContextual("let"),a=!1,o=this.containsEsc,u=new q,l=this.start,h=t>-1?this.parseExprSubscripts(u,"await"):this.parseExpression(!0,u);return this.type===b._in||(a=this.options.ecmaVersion>=6&&this.isContextual("of"))?(t>-1?(this.type===b._in&&this.unexpected(t),e.await=!0):a&&this.options.ecmaVersion>=8&&(h.start!==l||o||"Identifier"!==h.type||"async"!==h.name?this.options.ecmaVersion>=9&&(e.await=!1):this.unexpected()),i&&a&&this.raise(h.start,"The left-hand side of a for-of loop may not start with 'let'."),this.toAssignable(h,!1,u),this.checkLValPattern(h),this.parseForIn(e,h)):(this.checkExpressionErrors(u,!0),t>-1&&this.unexpected(t),this.parseFor(e,h))},X.parseFunctionStatement=function(e,t,s){return this.next(),this.parseFunction(e,J|(s?0:Q),!1,t)},X.parseIfStatement=function(e){return this.next(),e.test=this.parseParenExpression(),e.consequent=this.parseStatement("if"),e.alternate=this.eat(b._else)?this.parseStatement("if"):null,this.finishNode(e,"IfStatement")},X.parseReturnStatement=function(e){return this.inFunction||this.options.allowReturnOutsideFunction||this.raise(this.start,"'return' outside of function"),this.next(),this.eat(b.semi)||this.insertSemicolon()?e.argument=null:(e.argument=this.parseExpression(),this.semicolon()),this.finishNode(e,"ReturnStatement")},X.parseSwitchStatement=function(e){var t;this.next(),e.discriminant=this.parseParenExpression(),e.cases=[],this.expect(b.braceL),this.labels.push(Y),this.enterScope(0);for(var s=!1;this.type!==b.braceR;)if(this.type===b._case||this.type===b._default){var r=this.type===b._case;t&&this.finishNode(t,"SwitchCase"),e.cases.push(t=this.startNode()),t.consequent=[],this.next(),r?t.test=this.parseExpression():(s&&this.raiseRecoverable(this.lastTokStart,"Multiple default clauses"),s=!0,t.test=null),this.expect(b.colon)}else t||this.unexpected(),t.consequent.push(this.parseStatement(null));return this.exitScope(),t&&this.finishNode(t,"SwitchCase"),this.next(),this.labels.pop(),this.finishNode(e,"SwitchStatement")},X.parseThrowStatement=function(e){return this.next(),v.test(this.input.slice(this.lastTokEnd,this.start))&&this.raise(this.lastTokEnd,"Illegal newline after throw"),e.argument=this.parseExpression(),this.semicolon(),this.finishNode(e,"ThrowStatement")};var Z=[];X.parseCatchClauseParam=function(){var e=this.parseBindingAtom(),t="Identifier"===e.type;return this.enterScope(t?32:0),this.checkLValPattern(e,t?4:2),this.expect(b.parenR),e},X.parseTryStatement=function(e){if(this.next(),e.block=this.parseBlock(),e.handler=null,this.type===b._catch){var t=this.startNode();this.next(),this.eat(b.parenL)?t.param=this.parseCatchClauseParam():(this.options.ecmaVersion<10&&this.unexpected(),t.param=null,this.enterScope(0)),t.body=this.parseBlock(!1),this.exitScope(),e.handler=this.finishNode(t,"CatchClause")}return e.finalizer=this.eat(b._finally)?this.parseBlock():null,e.handler||e.finalizer||this.raise(e.start,"Missing catch or finally clause"),this.finishNode(e,"TryStatement")},X.parseVarStatement=function(e,t,s){return this.next(),this.parseVar(e,!1,t,s),this.semicolon(),this.finishNode(e,"VariableDeclaration")},X.parseWhileStatement=function(e){return this.next(),e.test=this.parseParenExpression(),this.labels.push(H),e.body=this.parseStatement("while"),this.labels.pop(),this.finishNode(e,"WhileStatement")},X.parseWithStatement=function(e){return this.strict&&this.raise(this.start,"'with' in strict mode"),this.next(),e.object=this.parseParenExpression(),e.body=this.parseStatement("with"),this.finishNode(e,"WithStatement")},X.parseEmptyStatement=function(e){return this.next(),this.finishNode(e,"EmptyStatement")},X.parseLabeledStatement=function(e,t,s,r){for(var n=0,i=this.labels;n=0;o--){var u=this.labels[o];if(u.statementStart!==e.start)break;u.statementStart=this.start,u.kind=a}return this.labels.push({name:t,kind:a,statementStart:this.start}),e.body=this.parseStatement(r?-1===r.indexOf("label")?r+"label":r:"label"),this.labels.pop(),e.label=s,this.finishNode(e,"LabeledStatement")},X.parseExpressionStatement=function(e,t){return e.expression=t,this.semicolon(),this.finishNode(e,"ExpressionStatement")},X.parseBlock=function(e,t,s){for(void 0===e&&(e=!0),void 0===t&&(t=this.startNode()),t.body=[],this.expect(b.braceL),e&&this.enterScope(0);this.type!==b.braceR;){var r=this.parseStatement(null);t.body.push(r)}return s&&(this.strict=!1),this.next(),e&&this.exitScope(),this.finishNode(t,"BlockStatement")},X.parseFor=function(e,t){return e.init=t,this.expect(b.semi),e.test=this.type===b.semi?null:this.parseExpression(),this.expect(b.semi),e.update=this.type===b.parenR?null:this.parseExpression(),this.expect(b.parenR),e.body=this.parseStatement("for"),this.exitScope(),this.labels.pop(),this.finishNode(e,"ForStatement")},X.parseForIn=function(e,t){var s=this.type===b._in;return this.next(),"VariableDeclaration"===t.type&&null!=t.declarations[0].init&&(!s||this.options.ecmaVersion<8||this.strict||"var"!==t.kind||"Identifier"!==t.declarations[0].id.type)&&this.raise(t.start,(s?"for-in":"for-of")+" loop variable declaration may not have an initializer"),e.left=t,e.right=s?this.parseExpression():this.parseMaybeAssign(),this.expect(b.parenR),e.body=this.parseStatement("for"),this.exitScope(),this.labels.pop(),this.finishNode(e,s?"ForInStatement":"ForOfStatement")},X.parseVar=function(e,t,s,r){for(e.declarations=[],e.kind=s;;){var n=this.startNode();if(this.parseVarId(n,s),this.eat(b.eq)?n.init=this.parseMaybeAssign(t):r||"const"!==s||this.type===b._in||this.options.ecmaVersion>=6&&this.isContextual("of")?r||"Identifier"===n.id.type||t&&(this.type===b._in||this.isContextual("of"))?n.init=null:this.raise(this.lastTokEnd,"Complex binding patterns require an initialization value"):this.unexpected(),e.declarations.push(this.finishNode(n,"VariableDeclarator")),!this.eat(b.comma))break}return e},X.parseVarId=function(e,t){e.id=this.parseBindingAtom(),this.checkLValPattern(e.id,"var"===t?1:2,!1)};var J=1,Q=2;function ee(e,t){var s=t.key.name,r=e[s],n="true";return"MethodDefinition"!==t.type||"get"!==t.kind&&"set"!==t.kind||(n=(t.static?"s":"i")+t.kind),"iget"===r&&"iset"===n||"iset"===r&&"iget"===n||"sget"===r&&"sset"===n||"sset"===r&&"sget"===n?(e[s]="true",!1):!!r||(e[s]=n,!1)}function te(e,t){var s=e.computed,r=e.key;return!s&&("Identifier"===r.type&&r.name===t||"Literal"===r.type&&r.value===t)}X.parseFunction=function(e,t,s,r,n){this.initFunction(e),(this.options.ecmaVersion>=9||this.options.ecmaVersion>=6&&!r)&&(this.type===b.star&&t&Q&&this.unexpected(),e.generator=this.eat(b.star)),this.options.ecmaVersion>=8&&(e.async=!!r),t&J&&(e.id=4&t&&this.type!==b.name?null:this.parseIdent(),!e.id||t&Q||this.checkLValSimple(e.id,this.strict||e.generator||e.async?this.treatFunctionsAsVar?1:2:3));var i=this.yieldPos,a=this.awaitPos,o=this.awaitIdentPos;return this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,this.enterScope(z(e.async,e.generator)),t&J||(e.id=this.type===b.name?this.parseIdent():null),this.parseFunctionParams(e),this.parseFunctionBody(e,s,!1,n),this.yieldPos=i,this.awaitPos=a,this.awaitIdentPos=o,this.finishNode(e,t&J?"FunctionDeclaration":"FunctionExpression")},X.parseFunctionParams=function(e){this.expect(b.parenL),e.params=this.parseBindingList(b.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams()},X.parseClass=function(e,t){this.next();var s=this.strict;this.strict=!0,this.parseClassId(e,t),this.parseClassSuper(e);var r=this.enterClassBody(),n=this.startNode(),i=!1;for(n.body=[],this.expect(b.braceL);this.type!==b.braceR;){var a=this.parseClassElement(null!==e.superClass);a&&(n.body.push(a),"MethodDefinition"===a.type&&"constructor"===a.kind?(i&&this.raiseRecoverable(a.start,"Duplicate constructor in the same class"),i=!0):a.key&&"PrivateIdentifier"===a.key.type&&ee(r,a)&&this.raiseRecoverable(a.key.start,"Identifier '#"+a.key.name+"' has already been declared"))}return this.strict=s,this.next(),e.body=this.finishNode(n,"ClassBody"),this.exitClassBody(),this.finishNode(e,t?"ClassDeclaration":"ClassExpression")},X.parseClassElement=function(e){if(this.eat(b.semi))return null;var t=this.options.ecmaVersion,s=this.startNode(),r="",n=!1,i=!1,a="method",o=!1;if(this.eatContextual("static")){if(t>=13&&this.eat(b.braceL))return this.parseClassStaticBlock(s),s;this.isClassElementNameStart()||this.type===b.star?o=!0:r="static"}if(s.static=o,!r&&t>=8&&this.eatContextual("async")&&(!this.isClassElementNameStart()&&this.type!==b.star||this.canInsertSemicolon()?r="async":i=!0),!r&&(t>=9||!i)&&this.eat(b.star)&&(n=!0),!r&&!i&&!n){var u=this.value;(this.eatContextual("get")||this.eatContextual("set"))&&(this.isClassElementNameStart()?a=u:r=u)}if(r?(s.computed=!1,s.key=this.startNodeAt(this.lastTokStart,this.lastTokStartLoc),s.key.name=r,this.finishNode(s.key,"Identifier")):this.parseClassElementName(s),t<13||this.type===b.parenL||"method"!==a||n||i){var l=!s.static&&te(s,"constructor"),h=l&&e;l&&"method"!==a&&this.raise(s.key.start,"Constructor can't have get/set modifier"),s.kind=l?"constructor":a,this.parseClassMethod(s,n,i,h)}else this.parseClassField(s);return s},X.isClassElementNameStart=function(){return this.type===b.name||this.type===b.privateId||this.type===b.num||this.type===b.string||this.type===b.bracketL||this.type.keyword},X.parseClassElementName=function(e){this.type===b.privateId?("constructor"===this.value&&this.raise(this.start,"Classes can't have an element named '#constructor'"),e.computed=!1,e.key=this.parsePrivateIdent()):this.parsePropertyName(e)},X.parseClassMethod=function(e,t,s,r){var n=e.key;"constructor"===e.kind?(t&&this.raise(n.start,"Constructor can't be a generator"),s&&this.raise(n.start,"Constructor can't be an async method")):e.static&&te(e,"prototype")&&this.raise(n.start,"Classes may not have a static property named prototype");var i=e.value=this.parseMethod(t,s,r);return"get"===e.kind&&0!==i.params.length&&this.raiseRecoverable(i.start,"getter should have no params"),"set"===e.kind&&1!==i.params.length&&this.raiseRecoverable(i.start,"setter should have exactly one param"),"set"===e.kind&&"RestElement"===i.params[0].type&&this.raiseRecoverable(i.params[0].start,"Setter cannot use rest params"),this.finishNode(e,"MethodDefinition")},X.parseClassField=function(e){if(te(e,"constructor")?this.raise(e.key.start,"Classes can't have a field named 'constructor'"):e.static&&te(e,"prototype")&&this.raise(e.key.start,"Classes can't have a static field named 'prototype'"),this.eat(b.eq)){var t=this.currentThisScope(),s=t.inClassFieldInit;t.inClassFieldInit=!0,e.value=this.parseMaybeAssign(),t.inClassFieldInit=s}else e.value=null;return this.semicolon(),this.finishNode(e,"PropertyDefinition")},X.parseClassStaticBlock=function(e){e.body=[];var t=this.labels;for(this.labels=[],this.enterScope(320);this.type!==b.braceR;){var s=this.parseStatement(null);e.body.push(s)}return this.next(),this.exitScope(),this.labels=t,this.finishNode(e,"StaticBlock")},X.parseClassId=function(e,t){this.type===b.name?(e.id=this.parseIdent(),t&&this.checkLValSimple(e.id,2,!1)):(!0===t&&this.unexpected(),e.id=null)},X.parseClassSuper=function(e){e.superClass=this.eat(b._extends)?this.parseExprSubscripts(null,!1):null},X.enterClassBody=function(){var e={declared:Object.create(null),used:[]};return this.privateNameStack.push(e),e.declared},X.exitClassBody=function(){var e=this.privateNameStack.pop(),t=e.declared,s=e.used;if(this.options.checkPrivateFields)for(var r=this.privateNameStack.length,n=0===r?null:this.privateNameStack[r-1],i=0;i=11&&(this.eatContextual("as")?(e.exported=this.parseModuleExportName(),this.checkExport(t,e.exported,this.lastTokStart)):e.exported=null),this.expectContextual("from"),this.type!==b.string&&this.unexpected(),e.source=this.parseExprAtom(),this.options.ecmaVersion>=16&&(e.attributes=this.parseWithClause()),this.semicolon(),this.finishNode(e,"ExportAllDeclaration")},X.parseExport=function(e,t){if(this.next(),this.eat(b.star))return this.parseExportAllDeclaration(e,t);if(this.eat(b._default))return this.checkExport(t,"default",this.lastTokStart),e.declaration=this.parseExportDefaultDeclaration(),this.finishNode(e,"ExportDefaultDeclaration");if(this.shouldParseExportStatement())e.declaration=this.parseExportDeclaration(e),"VariableDeclaration"===e.declaration.type?this.checkVariableExport(t,e.declaration.declarations):this.checkExport(t,e.declaration.id,e.declaration.id.start),e.specifiers=[],e.source=null;else{if(e.declaration=null,e.specifiers=this.parseExportSpecifiers(t),this.eatContextual("from"))this.type!==b.string&&this.unexpected(),e.source=this.parseExprAtom(),this.options.ecmaVersion>=16&&(e.attributes=this.parseWithClause());else{for(var s=0,r=e.specifiers;s=16&&(e.attributes=this.parseWithClause()),this.semicolon(),this.finishNode(e,"ImportDeclaration")},X.parseImportSpecifier=function(){var e=this.startNode();return e.imported=this.parseModuleExportName(),this.eatContextual("as")?e.local=this.parseIdent():(this.checkUnreserved(e.imported),e.local=e.imported),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportSpecifier")},X.parseImportDefaultSpecifier=function(){var e=this.startNode();return e.local=this.parseIdent(),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportDefaultSpecifier")},X.parseImportNamespaceSpecifier=function(){var e=this.startNode();return this.next(),this.expectContextual("as"),e.local=this.parseIdent(),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportNamespaceSpecifier")},X.parseImportSpecifiers=function(){var e=[],t=!0;if(this.type===b.name&&(e.push(this.parseImportDefaultSpecifier()),!this.eat(b.comma)))return e;if(this.type===b.star)return e.push(this.parseImportNamespaceSpecifier()),e;for(this.expect(b.braceL);!this.eat(b.braceR);){if(t)t=!1;else if(this.expect(b.comma),this.afterTrailingComma(b.braceR))break;e.push(this.parseImportSpecifier())}return e},X.parseWithClause=function(){var e=[];if(!this.eat(b._with))return e;this.expect(b.braceL);for(var t={},s=!0;!this.eat(b.braceR);){if(s)s=!1;else if(this.expect(b.comma),this.afterTrailingComma(b.braceR))break;var r=this.parseImportAttribute(),n="Identifier"===r.key.type?r.key.name:r.key.value;C(t,n)&&this.raiseRecoverable(r.key.start,"Duplicate attribute key '"+n+"'"),t[n]=!0,e.push(r)}return e},X.parseImportAttribute=function(){var e=this.startNode();return e.key=this.type===b.string?this.parseExprAtom():this.parseIdent("never"!==this.options.allowReserved),this.expect(b.colon),this.type!==b.string&&this.unexpected(),e.value=this.parseExprAtom(),this.finishNode(e,"ImportAttribute")},X.parseModuleExportName=function(){if(this.options.ecmaVersion>=13&&this.type===b.string){var e=this.parseLiteral(this.value);return R.test(e.value)&&this.raise(e.start,"An export name cannot include a lone surrogate."),e}return this.parseIdent(!0)},X.adaptDirectivePrologue=function(e){for(var t=0;t=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"string"==typeof e.expression.value&&('"'===this.input[e.start]||"'"===this.input[e.start])};var se=U.prototype;se.toAssignable=function(e,t,s){if(this.options.ecmaVersion>=6&&e)switch(e.type){case"Identifier":this.inAsync&&"await"===e.name&&this.raise(e.start,"Cannot use 'await' as identifier inside an async function");break;case"ObjectPattern":case"ArrayPattern":case"AssignmentPattern":case"RestElement":break;case"ObjectExpression":e.type="ObjectPattern",s&&this.checkPatternErrors(s,!0);for(var r=0,n=e.properties;r=8&&!o&&"async"===u.name&&!this.canInsertSemicolon()&&this.eat(b._function))return this.overrideContext(ne.f_expr),this.parseFunction(this.startNodeAt(i,a),0,!1,!0,t);if(n&&!this.canInsertSemicolon()){if(this.eat(b.arrow))return this.parseArrowExpression(this.startNodeAt(i,a),[u],!1,t);if(this.options.ecmaVersion>=8&&"async"===u.name&&this.type===b.name&&!o&&(!this.potentialArrowInForAwait||"of"!==this.value||this.containsEsc))return u=this.parseIdent(!1),!this.canInsertSemicolon()&&this.eat(b.arrow)||this.unexpected(),this.parseArrowExpression(this.startNodeAt(i,a),[u],!0,t)}return u;case b.regexp:var l=this.value;return(r=this.parseLiteral(l.value)).regex={pattern:l.pattern,flags:l.flags},r;case b.num:case b.string:return this.parseLiteral(this.value);case b._null:case b._true:case b._false:return(r=this.startNode()).value=this.type===b._null?null:this.type===b._true,r.raw=this.type.keyword,this.next(),this.finishNode(r,"Literal");case b.parenL:var h=this.start,c=this.parseParenAndDistinguishExpression(n,t);return e&&(e.parenthesizedAssign<0&&!this.isSimpleAssignTarget(c)&&(e.parenthesizedAssign=h),e.parenthesizedBind<0&&(e.parenthesizedBind=h)),c;case b.bracketL:return r=this.startNode(),this.next(),r.elements=this.parseExprList(b.bracketR,!0,!0,e),this.finishNode(r,"ArrayExpression");case b.braceL:return this.overrideContext(ne.b_expr),this.parseObj(!1,e);case b._function:return r=this.startNode(),this.next(),this.parseFunction(r,0);case b._class:return this.parseClass(this.startNode(),!1);case b._new:return this.parseNew();case b.backQuote:return this.parseTemplate();case b._import:return this.options.ecmaVersion>=11?this.parseExprImport(s):this.unexpected();default:return this.parseExprAtomDefault()}},ae.parseExprAtomDefault=function(){this.unexpected()},ae.parseExprImport=function(e){var t=this.startNode();if(this.containsEsc&&this.raiseRecoverable(this.start,"Escape sequence in keyword import"),this.next(),this.type===b.parenL&&!e)return this.parseDynamicImport(t);if(this.type===b.dot){var s=this.startNodeAt(t.start,t.loc&&t.loc.start);return s.name="import",t.meta=this.finishNode(s,"Identifier"),this.parseImportMeta(t)}this.unexpected()},ae.parseDynamicImport=function(e){if(this.next(),e.source=this.parseMaybeAssign(),this.options.ecmaVersion>=16)this.eat(b.parenR)?e.options=null:(this.expect(b.comma),this.afterTrailingComma(b.parenR)?e.options=null:(e.options=this.parseMaybeAssign(),this.eat(b.parenR)||(this.expect(b.comma),this.afterTrailingComma(b.parenR)||this.unexpected())));else if(!this.eat(b.parenR)){var t=this.start;this.eat(b.comma)&&this.eat(b.parenR)?this.raiseRecoverable(t,"Trailing comma is not allowed in import()"):this.unexpected(t)}return this.finishNode(e,"ImportExpression")},ae.parseImportMeta=function(e){this.next();var t=this.containsEsc;return e.property=this.parseIdent(!0),"meta"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for import is 'import.meta'"),t&&this.raiseRecoverable(e.start,"'import.meta' must not contain escaped characters"),"module"===this.options.sourceType||this.options.allowImportExportEverywhere||this.raiseRecoverable(e.start,"Cannot use 'import.meta' outside a module"),this.finishNode(e,"MetaProperty")},ae.parseLiteral=function(e){var t=this.startNode();return t.value=e,t.raw=this.input.slice(this.start,this.end),110===t.raw.charCodeAt(t.raw.length-1)&&(t.bigint=t.raw.slice(0,-1).replace(/_/g,"")),this.next(),this.finishNode(t,"Literal")},ae.parseParenExpression=function(){this.expect(b.parenL);var e=this.parseExpression();return this.expect(b.parenR),e},ae.shouldParseArrow=function(e){return!this.canInsertSemicolon()},ae.parseParenAndDistinguishExpression=function(e,t){var s,r=this.start,n=this.startLoc,i=this.options.ecmaVersion>=8;if(this.options.ecmaVersion>=6){this.next();var a,o=this.start,u=this.startLoc,l=[],h=!0,c=!1,p=new q,d=this.yieldPos,f=this.awaitPos;for(this.yieldPos=0,this.awaitPos=0;this.type!==b.parenR;){if(h?h=!1:this.expect(b.comma),i&&this.afterTrailingComma(b.parenR,!0)){c=!0;break}if(this.type===b.ellipsis){a=this.start,l.push(this.parseParenItem(this.parseRestBinding())),this.type===b.comma&&this.raiseRecoverable(this.start,"Comma is not permitted after the rest element");break}l.push(this.parseMaybeAssign(!1,p,this.parseParenItem))}var m=this.lastTokEnd,g=this.lastTokEndLoc;if(this.expect(b.parenR),e&&this.shouldParseArrow(l)&&this.eat(b.arrow))return this.checkPatternErrors(p,!1),this.checkYieldAwaitInDefaultParams(),this.yieldPos=d,this.awaitPos=f,this.parseParenArrowList(r,n,l,t);l.length&&!c||this.unexpected(this.lastTokStart),a&&this.unexpected(a),this.checkExpressionErrors(p,!0),this.yieldPos=d||this.yieldPos,this.awaitPos=f||this.awaitPos,l.length>1?((s=this.startNodeAt(o,u)).expressions=l,this.finishNodeAt(s,"SequenceExpression",m,g)):s=l[0]}else s=this.parseParenExpression();if(this.options.preserveParens){var y=this.startNodeAt(r,n);return y.expression=s,this.finishNode(y,"ParenthesizedExpression")}return s},ae.parseParenItem=function(e){return e},ae.parseParenArrowList=function(e,t,s,r){return this.parseArrowExpression(this.startNodeAt(e,t),s,!1,r)};var le=[];ae.parseNew=function(){this.containsEsc&&this.raiseRecoverable(this.start,"Escape sequence in keyword new");var e=this.startNode();if(this.next(),this.options.ecmaVersion>=6&&this.type===b.dot){var t=this.startNodeAt(e.start,e.loc&&e.loc.start);t.name="new",e.meta=this.finishNode(t,"Identifier"),this.next();var s=this.containsEsc;return e.property=this.parseIdent(!0),"target"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for new is 'new.target'"),s&&this.raiseRecoverable(e.start,"'new.target' must not contain escaped characters"),this.allowNewDotTarget||this.raiseRecoverable(e.start,"'new.target' can only be used in functions and class static block"),this.finishNode(e,"MetaProperty")}var r=this.start,n=this.startLoc;return e.callee=this.parseSubscripts(this.parseExprAtom(null,!1,!0),r,n,!0,!1),this.eat(b.parenL)?e.arguments=this.parseExprList(b.parenR,this.options.ecmaVersion>=8,!1):e.arguments=le,this.finishNode(e,"NewExpression")},ae.parseTemplateElement=function(e){var t=e.isTagged,s=this.startNode();return this.type===b.invalidTemplate?(t||this.raiseRecoverable(this.start,"Bad escape sequence in untagged template literal"),s.value={raw:this.value.replace(/\r\n?/g,"\n"),cooked:null}):s.value={raw:this.input.slice(this.start,this.end).replace(/\r\n?/g,"\n"),cooked:this.value},this.next(),s.tail=this.type===b.backQuote,this.finishNode(s,"TemplateElement")},ae.parseTemplate=function(e){void 0===e&&(e={});var t=e.isTagged;void 0===t&&(t=!1);var s=this.startNode();this.next(),s.expressions=[];var r=this.parseTemplateElement({isTagged:t});for(s.quasis=[r];!r.tail;)this.type===b.eof&&this.raise(this.pos,"Unterminated template literal"),this.expect(b.dollarBraceL),s.expressions.push(this.parseExpression()),this.expect(b.braceR),s.quasis.push(r=this.parseTemplateElement({isTagged:t}));return this.next(),this.finishNode(s,"TemplateLiteral")},ae.isAsyncProp=function(e){return!e.computed&&"Identifier"===e.key.type&&"async"===e.key.name&&(this.type===b.name||this.type===b.num||this.type===b.string||this.type===b.bracketL||this.type.keyword||this.options.ecmaVersion>=9&&this.type===b.star)&&!v.test(this.input.slice(this.lastTokEnd,this.start))},ae.parseObj=function(e,t){var s=this.startNode(),r=!0,n={};for(s.properties=[],this.next();!this.eat(b.braceR);){if(r)r=!1;else if(this.expect(b.comma),this.options.ecmaVersion>=5&&this.afterTrailingComma(b.braceR))break;var i=this.parseProperty(e,t);e||this.checkPropClash(i,n,t),s.properties.push(i)}return this.finishNode(s,e?"ObjectPattern":"ObjectExpression")},ae.parseProperty=function(e,t){var s,r,n,i,a=this.startNode();if(this.options.ecmaVersion>=9&&this.eat(b.ellipsis))return e?(a.argument=this.parseIdent(!1),this.type===b.comma&&this.raiseRecoverable(this.start,"Comma is not permitted after the rest element"),this.finishNode(a,"RestElement")):(a.argument=this.parseMaybeAssign(!1,t),this.type===b.comma&&t&&t.trailingComma<0&&(t.trailingComma=this.start),this.finishNode(a,"SpreadElement"));this.options.ecmaVersion>=6&&(a.method=!1,a.shorthand=!1,(e||t)&&(n=this.start,i=this.startLoc),e||(s=this.eat(b.star)));var o=this.containsEsc;return this.parsePropertyName(a),!e&&!o&&this.options.ecmaVersion>=8&&!s&&this.isAsyncProp(a)?(r=!0,s=this.options.ecmaVersion>=9&&this.eat(b.star),this.parsePropertyName(a)):r=!1,this.parsePropertyValue(a,e,s,r,n,i,t,o),this.finishNode(a,"Property")},ae.parseGetterSetter=function(e){e.kind=e.key.name,this.parsePropertyName(e),e.value=this.parseMethod(!1);var t="get"===e.kind?0:1;if(e.value.params.length!==t){var s=e.value.start;"get"===e.kind?this.raiseRecoverable(s,"getter should have no params"):this.raiseRecoverable(s,"setter should have exactly one param")}else"set"===e.kind&&"RestElement"===e.value.params[0].type&&this.raiseRecoverable(e.value.params[0].start,"Setter cannot use rest params")},ae.parsePropertyValue=function(e,t,s,r,n,i,a,o){(s||r)&&this.type===b.colon&&this.unexpected(),this.eat(b.colon)?(e.value=t?this.parseMaybeDefault(this.start,this.startLoc):this.parseMaybeAssign(!1,a),e.kind="init"):this.options.ecmaVersion>=6&&this.type===b.parenL?(t&&this.unexpected(),e.kind="init",e.method=!0,e.value=this.parseMethod(s,r)):t||o||!(this.options.ecmaVersion>=5)||e.computed||"Identifier"!==e.key.type||"get"!==e.key.name&&"set"!==e.key.name||this.type===b.comma||this.type===b.braceR||this.type===b.eq?this.options.ecmaVersion>=6&&!e.computed&&"Identifier"===e.key.type?((s||r)&&this.unexpected(),this.checkUnreserved(e.key),"await"!==e.key.name||this.awaitIdentPos||(this.awaitIdentPos=n),e.kind="init",t?e.value=this.parseMaybeDefault(n,i,this.copyNode(e.key)):this.type===b.eq&&a?(a.shorthandAssign<0&&(a.shorthandAssign=this.start),e.value=this.parseMaybeDefault(n,i,this.copyNode(e.key))):e.value=this.copyNode(e.key),e.shorthand=!0):this.unexpected():((s||r)&&this.unexpected(),this.parseGetterSetter(e))},ae.parsePropertyName=function(e){if(this.options.ecmaVersion>=6){if(this.eat(b.bracketL))return e.computed=!0,e.key=this.parseMaybeAssign(),this.expect(b.bracketR),e.key;e.computed=!1}return e.key=this.type===b.num||this.type===b.string?this.parseExprAtom():this.parseIdent("never"!==this.options.allowReserved)},ae.initFunction=function(e){e.id=null,this.options.ecmaVersion>=6&&(e.generator=e.expression=!1),this.options.ecmaVersion>=8&&(e.async=!1)},ae.parseMethod=function(e,t,s){var r=this.startNode(),n=this.yieldPos,i=this.awaitPos,a=this.awaitIdentPos;return this.initFunction(r),this.options.ecmaVersion>=6&&(r.generator=e),this.options.ecmaVersion>=8&&(r.async=!!t),this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,this.enterScope(64|z(t,r.generator)|(s?128:0)),this.expect(b.parenL),r.params=this.parseBindingList(b.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams(),this.parseFunctionBody(r,!1,!0,!1),this.yieldPos=n,this.awaitPos=i,this.awaitIdentPos=a,this.finishNode(r,"FunctionExpression")},ae.parseArrowExpression=function(e,t,s,r){var n=this.yieldPos,i=this.awaitPos,a=this.awaitIdentPos;return this.enterScope(16|z(s,!1)),this.initFunction(e),this.options.ecmaVersion>=8&&(e.async=!!s),this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,e.params=this.toAssignableList(t,!0),this.parseFunctionBody(e,!0,!1,r),this.yieldPos=n,this.awaitPos=i,this.awaitIdentPos=a,this.finishNode(e,"ArrowFunctionExpression")},ae.parseFunctionBody=function(e,t,s,r){var n=t&&this.type!==b.braceL,i=this.strict,a=!1;if(n)e.body=this.parseMaybeAssign(r),e.expression=!0,this.checkParams(e,!1);else{var o=this.options.ecmaVersion>=7&&!this.isSimpleParamList(e.params);i&&!o||(a=this.strictDirective(this.end))&&o&&this.raiseRecoverable(e.start,"Illegal 'use strict' directive in function with non-simple parameter list");var u=this.labels;this.labels=[],a&&(this.strict=!0),this.checkParams(e,!i&&!a&&!t&&!s&&this.isSimpleParamList(e.params)),this.strict&&e.id&&this.checkLValSimple(e.id,5),e.body=this.parseBlock(!1,void 0,a&&!i),e.expression=!1,this.adaptDirectivePrologue(e.body.body),this.labels=u}this.exitScope()},ae.isSimpleParamList=function(e){for(var t=0,s=e;t-1||n.functions.indexOf(e)>-1||n.var.indexOf(e)>-1,n.lexical.push(e),this.inModule&&1&n.flags&&delete this.undefinedExports[e]}else if(4===t)this.currentScope().lexical.push(e);else if(3===t){var i=this.currentScope();r=this.treatFunctionsAsVar?i.lexical.indexOf(e)>-1:i.lexical.indexOf(e)>-1||i.var.indexOf(e)>-1,i.functions.push(e)}else for(var a=this.scopeStack.length-1;a>=0;--a){var o=this.scopeStack[a];if(o.lexical.indexOf(e)>-1&&!(32&o.flags&&o.lexical[0]===e)||!this.treatFunctionsAsVarInScope(o)&&o.functions.indexOf(e)>-1){r=!0;break}if(o.var.push(e),this.inModule&&1&o.flags&&delete this.undefinedExports[e],259&o.flags)break}r&&this.raiseRecoverable(s,"Identifier '"+e+"' has already been declared")},ce.checkLocalExport=function(e){-1===this.scopeStack[0].lexical.indexOf(e.name)&&-1===this.scopeStack[0].var.indexOf(e.name)&&(this.undefinedExports[e.name]=e)},ce.currentScope=function(){return this.scopeStack[this.scopeStack.length-1]},ce.currentVarScope=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e];if(259&t.flags)return t}},ce.currentThisScope=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e];if(259&t.flags&&!(16&t.flags))return t}};var de=function(e,t,s){this.type="",this.start=t,this.end=0,e.options.locations&&(this.loc=new M(e,s)),e.options.directSourceFile&&(this.sourceFile=e.options.directSourceFile),e.options.ranges&&(this.range=[t,0])},fe=U.prototype;function me(e,t,s,r){return e.type=t,e.end=s,this.options.locations&&(e.loc.end=r),this.options.ranges&&(e.range[1]=s),e}fe.startNode=function(){return new de(this,this.start,this.startLoc)},fe.startNodeAt=function(e,t){return new de(this,e,t)},fe.finishNode=function(e,t){return me.call(this,e,t,this.lastTokEnd,this.lastTokEndLoc)},fe.finishNodeAt=function(e,t,s,r){return me.call(this,e,t,s,r)},fe.copyNode=function(e){var t=new de(this,e.start,this.startLoc);for(var s in e)t[s]=e[s];return t};var ge="ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS",ye=ge+" Extended_Pictographic",xe=ye+" EBase EComp EMod EPres ExtPict",be={9:ge,10:ye,11:ye,12:xe,13:xe,14:xe},ve={9:"",10:"",11:"",12:"",13:"",14:"Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji"},Se="Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu",Te="Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb",Ae=Te+" Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd",we=Ae+" Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho",_e=we+" Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi",Ee=_e+" Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith",Ie={9:Te,10:Ae,11:we,12:_e,13:Ee,14:Ee+" Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz"},ke={};function Ce(e){var t=ke[e]={binary:F(be[e]+" "+Se),binaryOfStrings:F(ve[e]),nonBinary:{General_Category:F(Se),Script:F(Ie[e])}};t.nonBinary.Script_Extensions=t.nonBinary.Script,t.nonBinary.gc=t.nonBinary.General_Category,t.nonBinary.sc=t.nonBinary.Script,t.nonBinary.scx=t.nonBinary.Script_Extensions}for(var Le=0,De=[9,10,11,12,13,14];Le=6?"uy":"")+(e.options.ecmaVersion>=9?"s":"")+(e.options.ecmaVersion>=13?"d":"")+(e.options.ecmaVersion>=15?"v":""),this.unicodeProperties=ke[e.options.ecmaVersion>=14?14:e.options.ecmaVersion],this.source="",this.flags="",this.start=0,this.switchU=!1,this.switchV=!1,this.switchN=!1,this.pos=0,this.lastIntValue=0,this.lastStringValue="",this.lastAssertionIsQuantifiable=!1,this.numCapturingParens=0,this.maxBackReference=0,this.groupNames=Object.create(null),this.backReferenceNames=[],this.branchID=null};function Ne(e){return 105===e||109===e||115===e}function Me(e){return 36===e||e>=40&&e<=43||46===e||63===e||e>=91&&e<=94||e>=123&&e<=125}function Ge(e){return e>=65&&e<=90||e>=97&&e<=122}function Oe(e){return Ge(e)||95===e}function Ve(e){return Oe(e)||Pe(e)}function Pe(e){return e>=48&&e<=57}function Be(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}function ze(e){return e>=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:e-48}function Ue(e){return e>=48&&e<=55}Re.prototype.reset=function(e,t,s){var r=-1!==s.indexOf("v"),n=-1!==s.indexOf("u");this.start=0|e,this.source=t+"",this.flags=s,r&&this.parser.options.ecmaVersion>=15?(this.switchU=!0,this.switchV=!0,this.switchN=!0):(this.switchU=n&&this.parser.options.ecmaVersion>=6,this.switchV=!1,this.switchN=n&&this.parser.options.ecmaVersion>=9)},Re.prototype.raise=function(e){this.parser.raiseRecoverable(this.start,"Invalid regular expression: /"+this.source+"/: "+e)},Re.prototype.at=function(e,t){void 0===t&&(t=!1);var s=this.source,r=s.length;if(e>=r)return-1;var n=s.charCodeAt(e);if(!t&&!this.switchU||n<=55295||n>=57344||e+1>=r)return n;var i=s.charCodeAt(e+1);return i>=56320&&i<=57343?(n<<10)+i-56613888:n},Re.prototype.nextIndex=function(e,t){void 0===t&&(t=!1);var s=this.source,r=s.length;if(e>=r)return r;var n,i=s.charCodeAt(e);return!t&&!this.switchU||i<=55295||i>=57344||e+1>=r||(n=s.charCodeAt(e+1))<56320||n>57343?e+1:e+2},Re.prototype.current=function(e){return void 0===e&&(e=!1),this.at(this.pos,e)},Re.prototype.lookahead=function(e){return void 0===e&&(e=!1),this.at(this.nextIndex(this.pos,e),e)},Re.prototype.advance=function(e){void 0===e&&(e=!1),this.pos=this.nextIndex(this.pos,e)},Re.prototype.eat=function(e,t){return void 0===t&&(t=!1),this.current(t)===e&&(this.advance(t),!0)},Re.prototype.eatChars=function(e,t){void 0===t&&(t=!1);for(var s=this.pos,r=0,n=e;r-1&&this.raise(e.start,"Duplicate regular expression flag"),"u"===a&&(r=!0),"v"===a&&(n=!0)}this.options.ecmaVersion>=15&&r&&n&&this.raise(e.start,"Invalid regular expression flag")},Fe.validateRegExpPattern=function(e){this.regexp_pattern(e),!e.switchN&&this.options.ecmaVersion>=9&&function(e){for(var t in e)return!0;return!1}(e.groupNames)&&(e.switchN=!0,this.regexp_pattern(e))},Fe.regexp_pattern=function(e){e.pos=0,e.lastIntValue=0,e.lastStringValue="",e.lastAssertionIsQuantifiable=!1,e.numCapturingParens=0,e.maxBackReference=0,e.groupNames=Object.create(null),e.backReferenceNames.length=0,e.branchID=null,this.regexp_disjunction(e),e.pos!==e.source.length&&(e.eat(41)&&e.raise("Unmatched ')'"),(e.eat(93)||e.eat(125))&&e.raise("Lone quantifier brackets")),e.maxBackReference>e.numCapturingParens&&e.raise("Invalid escape");for(var t=0,s=e.backReferenceNames;t=16;for(t&&(e.branchID=new $e(e.branchID,null)),this.regexp_alternative(e);e.eat(124);)t&&(e.branchID=e.branchID.sibling()),this.regexp_alternative(e);t&&(e.branchID=e.branchID.parent),this.regexp_eatQuantifier(e,!0)&&e.raise("Nothing to repeat"),e.eat(123)&&e.raise("Lone quantifier brackets")},Fe.regexp_alternative=function(e){for(;e.pos=9&&(s=e.eat(60)),e.eat(61)||e.eat(33))return this.regexp_disjunction(e),e.eat(41)||e.raise("Unterminated group"),e.lastAssertionIsQuantifiable=!s,!0}return e.pos=t,!1},Fe.regexp_eatQuantifier=function(e,t){return void 0===t&&(t=!1),!!this.regexp_eatQuantifierPrefix(e,t)&&(e.eat(63),!0)},Fe.regexp_eatQuantifierPrefix=function(e,t){return e.eat(42)||e.eat(43)||e.eat(63)||this.regexp_eatBracedQuantifier(e,t)},Fe.regexp_eatBracedQuantifier=function(e,t){var s=e.pos;if(e.eat(123)){var r=0,n=-1;if(this.regexp_eatDecimalDigits(e)&&(r=e.lastIntValue,e.eat(44)&&this.regexp_eatDecimalDigits(e)&&(n=e.lastIntValue),e.eat(125)))return-1!==n&&n=16){var s=this.regexp_eatModifiers(e),r=e.eat(45);if(s||r){for(var n=0;n-1&&e.raise("Duplicate regular expression modifiers")}if(r){var a=this.regexp_eatModifiers(e);s||a||58!==e.current()||e.raise("Invalid regular expression modifiers");for(var o=0;o-1||s.indexOf(u)>-1)&&e.raise("Duplicate regular expression modifiers")}}}}if(e.eat(58)){if(this.regexp_disjunction(e),e.eat(41))return!0;e.raise("Unterminated group")}}e.pos=t}return!1},Fe.regexp_eatCapturingGroup=function(e){if(e.eat(40)){if(this.options.ecmaVersion>=9?this.regexp_groupSpecifier(e):63===e.current()&&e.raise("Invalid group"),this.regexp_disjunction(e),e.eat(41))return e.numCapturingParens+=1,!0;e.raise("Unterminated group")}return!1},Fe.regexp_eatModifiers=function(e){for(var t="",s=0;-1!==(s=e.current())&&Ne(s);)t+=$(s),e.advance();return t},Fe.regexp_eatExtendedAtom=function(e){return e.eat(46)||this.regexp_eatReverseSolidusAtomEscape(e)||this.regexp_eatCharacterClass(e)||this.regexp_eatUncapturingGroup(e)||this.regexp_eatCapturingGroup(e)||this.regexp_eatInvalidBracedQuantifier(e)||this.regexp_eatExtendedPatternCharacter(e)},Fe.regexp_eatInvalidBracedQuantifier=function(e){return this.regexp_eatBracedQuantifier(e,!0)&&e.raise("Nothing to repeat"),!1},Fe.regexp_eatSyntaxCharacter=function(e){var t=e.current();return!!Me(t)&&(e.lastIntValue=t,e.advance(),!0)},Fe.regexp_eatPatternCharacters=function(e){for(var t=e.pos,s=0;-1!==(s=e.current())&&!Me(s);)e.advance();return e.pos!==t},Fe.regexp_eatExtendedPatternCharacter=function(e){var t=e.current();return!(-1===t||36===t||t>=40&&t<=43||46===t||63===t||91===t||94===t||124===t||(e.advance(),0))},Fe.regexp_groupSpecifier=function(e){if(e.eat(63)){this.regexp_eatGroupName(e)||e.raise("Invalid group");var t=this.options.ecmaVersion>=16,s=e.groupNames[e.lastStringValue];if(s)if(t)for(var r=0,n=s;r=11,r=e.current(s);return e.advance(s),92===r&&this.regexp_eatRegExpUnicodeEscapeSequence(e,s)&&(r=e.lastIntValue),function(e){return c(e,!0)||36===e||95===e}(r)?(e.lastIntValue=r,!0):(e.pos=t,!1)},Fe.regexp_eatRegExpIdentifierPart=function(e){var t=e.pos,s=this.options.ecmaVersion>=11,r=e.current(s);return e.advance(s),92===r&&this.regexp_eatRegExpUnicodeEscapeSequence(e,s)&&(r=e.lastIntValue),function(e){return p(e,!0)||36===e||95===e||8204===e||8205===e}(r)?(e.lastIntValue=r,!0):(e.pos=t,!1)},Fe.regexp_eatAtomEscape=function(e){return!!(this.regexp_eatBackReference(e)||this.regexp_eatCharacterClassEscape(e)||this.regexp_eatCharacterEscape(e)||e.switchN&&this.regexp_eatKGroupName(e))||(e.switchU&&(99===e.current()&&e.raise("Invalid unicode escape"),e.raise("Invalid escape")),!1)},Fe.regexp_eatBackReference=function(e){var t=e.pos;if(this.regexp_eatDecimalEscape(e)){var s=e.lastIntValue;if(e.switchU)return s>e.maxBackReference&&(e.maxBackReference=s),!0;if(s<=e.numCapturingParens)return!0;e.pos=t}return!1},Fe.regexp_eatKGroupName=function(e){if(e.eat(107)){if(this.regexp_eatGroupName(e))return e.backReferenceNames.push(e.lastStringValue),!0;e.raise("Invalid named reference")}return!1},Fe.regexp_eatCharacterEscape=function(e){return this.regexp_eatControlEscape(e)||this.regexp_eatCControlLetter(e)||this.regexp_eatZero(e)||this.regexp_eatHexEscapeSequence(e)||this.regexp_eatRegExpUnicodeEscapeSequence(e,!1)||!e.switchU&&this.regexp_eatLegacyOctalEscapeSequence(e)||this.regexp_eatIdentityEscape(e)},Fe.regexp_eatCControlLetter=function(e){var t=e.pos;if(e.eat(99)){if(this.regexp_eatControlLetter(e))return!0;e.pos=t}return!1},Fe.regexp_eatZero=function(e){return 48===e.current()&&!Pe(e.lookahead())&&(e.lastIntValue=0,e.advance(),!0)},Fe.regexp_eatControlEscape=function(e){var t=e.current();return 116===t?(e.lastIntValue=9,e.advance(),!0):110===t?(e.lastIntValue=10,e.advance(),!0):118===t?(e.lastIntValue=11,e.advance(),!0):102===t?(e.lastIntValue=12,e.advance(),!0):114===t&&(e.lastIntValue=13,e.advance(),!0)},Fe.regexp_eatControlLetter=function(e){var t=e.current();return!!Ge(t)&&(e.lastIntValue=t%32,e.advance(),!0)},Fe.regexp_eatRegExpUnicodeEscapeSequence=function(e,t){void 0===t&&(t=!1);var s,r=e.pos,n=t||e.switchU;if(e.eat(117)){if(this.regexp_eatFixedHexDigits(e,4)){var i=e.lastIntValue;if(n&&i>=55296&&i<=56319){var a=e.pos;if(e.eat(92)&&e.eat(117)&&this.regexp_eatFixedHexDigits(e,4)){var o=e.lastIntValue;if(o>=56320&&o<=57343)return e.lastIntValue=1024*(i-55296)+(o-56320)+65536,!0}e.pos=a,e.lastIntValue=i}return!0}if(n&&e.eat(123)&&this.regexp_eatHexDigits(e)&&e.eat(125)&&(s=e.lastIntValue)>=0&&s<=1114111)return!0;n&&e.raise("Invalid unicode escape"),e.pos=r}return!1},Fe.regexp_eatIdentityEscape=function(e){if(e.switchU)return!!this.regexp_eatSyntaxCharacter(e)||!!e.eat(47)&&(e.lastIntValue=47,!0);var t=e.current();return!(99===t||e.switchN&&107===t||(e.lastIntValue=t,e.advance(),0))},Fe.regexp_eatDecimalEscape=function(e){e.lastIntValue=0;var t=e.current();if(t>=49&&t<=57){do{e.lastIntValue=10*e.lastIntValue+(t-48),e.advance()}while((t=e.current())>=48&&t<=57);return!0}return!1},Fe.regexp_eatCharacterClassEscape=function(e){var t=e.current();if(function(e){return 100===e||68===e||115===e||83===e||119===e||87===e}(t))return e.lastIntValue=-1,e.advance(),1;var s=!1;if(e.switchU&&this.options.ecmaVersion>=9&&((s=80===t)||112===t)){var r;if(e.lastIntValue=-1,e.advance(),e.eat(123)&&(r=this.regexp_eatUnicodePropertyValueExpression(e))&&e.eat(125))return s&&2===r&&e.raise("Invalid property name"),r;e.raise("Invalid property name")}return 0},Fe.regexp_eatUnicodePropertyValueExpression=function(e){var t=e.pos;if(this.regexp_eatUnicodePropertyName(e)&&e.eat(61)){var s=e.lastStringValue;if(this.regexp_eatUnicodePropertyValue(e)){var r=e.lastStringValue;return this.regexp_validateUnicodePropertyNameAndValue(e,s,r),1}}if(e.pos=t,this.regexp_eatLoneUnicodePropertyNameOrValue(e)){var n=e.lastStringValue;return this.regexp_validateUnicodePropertyNameOrValue(e,n)}return 0},Fe.regexp_validateUnicodePropertyNameAndValue=function(e,t,s){C(e.unicodeProperties.nonBinary,t)||e.raise("Invalid property name"),e.unicodeProperties.nonBinary[t].test(s)||e.raise("Invalid property value")},Fe.regexp_validateUnicodePropertyNameOrValue=function(e,t){return e.unicodeProperties.binary.test(t)?1:e.switchV&&e.unicodeProperties.binaryOfStrings.test(t)?2:void e.raise("Invalid property name")},Fe.regexp_eatUnicodePropertyName=function(e){var t=0;for(e.lastStringValue="";Oe(t=e.current());)e.lastStringValue+=$(t),e.advance();return""!==e.lastStringValue},Fe.regexp_eatUnicodePropertyValue=function(e){var t=0;for(e.lastStringValue="";Ve(t=e.current());)e.lastStringValue+=$(t),e.advance();return""!==e.lastStringValue},Fe.regexp_eatLoneUnicodePropertyNameOrValue=function(e){return this.regexp_eatUnicodePropertyValue(e)},Fe.regexp_eatCharacterClass=function(e){if(e.eat(91)){var t=e.eat(94),s=this.regexp_classContents(e);return e.eat(93)||e.raise("Unterminated character class"),t&&2===s&&e.raise("Negated character class may contain strings"),!0}return!1},Fe.regexp_classContents=function(e){return 93===e.current()?1:e.switchV?this.regexp_classSetExpression(e):(this.regexp_nonEmptyClassRanges(e),1)},Fe.regexp_nonEmptyClassRanges=function(e){for(;this.regexp_eatClassAtom(e);){var t=e.lastIntValue;if(e.eat(45)&&this.regexp_eatClassAtom(e)){var s=e.lastIntValue;!e.switchU||-1!==t&&-1!==s||e.raise("Invalid character class"),-1!==t&&-1!==s&&t>s&&e.raise("Range out of order in character class")}}},Fe.regexp_eatClassAtom=function(e){var t=e.pos;if(e.eat(92)){if(this.regexp_eatClassEscape(e))return!0;if(e.switchU){var s=e.current();(99===s||Ue(s))&&e.raise("Invalid class escape"),e.raise("Invalid escape")}e.pos=t}var r=e.current();return 93!==r&&(e.lastIntValue=r,e.advance(),!0)},Fe.regexp_eatClassEscape=function(e){var t=e.pos;if(e.eat(98))return e.lastIntValue=8,!0;if(e.switchU&&e.eat(45))return e.lastIntValue=45,!0;if(!e.switchU&&e.eat(99)){if(this.regexp_eatClassControlLetter(e))return!0;e.pos=t}return this.regexp_eatCharacterClassEscape(e)||this.regexp_eatCharacterEscape(e)},Fe.regexp_classSetExpression=function(e){var t,s=1;if(this.regexp_eatClassSetRange(e));else if(t=this.regexp_eatClassSetOperand(e)){2===t&&(s=2);for(var r=e.pos;e.eatChars([38,38]);)38!==e.current()&&(t=this.regexp_eatClassSetOperand(e))?2!==t&&(s=1):e.raise("Invalid character in character class");if(r!==e.pos)return s;for(;e.eatChars([45,45]);)this.regexp_eatClassSetOperand(e)||e.raise("Invalid character in character class");if(r!==e.pos)return s}else e.raise("Invalid character in character class");for(;;)if(!this.regexp_eatClassSetRange(e)){if(!(t=this.regexp_eatClassSetOperand(e)))return s;2===t&&(s=2)}},Fe.regexp_eatClassSetRange=function(e){var t=e.pos;if(this.regexp_eatClassSetCharacter(e)){var s=e.lastIntValue;if(e.eat(45)&&this.regexp_eatClassSetCharacter(e)){var r=e.lastIntValue;return-1!==s&&-1!==r&&s>r&&e.raise("Range out of order in character class"),!0}e.pos=t}return!1},Fe.regexp_eatClassSetOperand=function(e){return this.regexp_eatClassSetCharacter(e)?1:this.regexp_eatClassStringDisjunction(e)||this.regexp_eatNestedClass(e)},Fe.regexp_eatNestedClass=function(e){var t=e.pos;if(e.eat(91)){var s=e.eat(94),r=this.regexp_classContents(e);if(e.eat(93))return s&&2===r&&e.raise("Negated character class may contain strings"),r;e.pos=t}if(e.eat(92)){var n=this.regexp_eatCharacterClassEscape(e);if(n)return n;e.pos=t}return null},Fe.regexp_eatClassStringDisjunction=function(e){var t=e.pos;if(e.eatChars([92,113])){if(e.eat(123)){var s=this.regexp_classStringDisjunctionContents(e);if(e.eat(125))return s}else e.raise("Invalid escape");e.pos=t}return null},Fe.regexp_classStringDisjunctionContents=function(e){for(var t=this.regexp_classString(e);e.eat(124);)2===this.regexp_classString(e)&&(t=2);return t},Fe.regexp_classString=function(e){for(var t=0;this.regexp_eatClassSetCharacter(e);)t++;return 1===t?1:2},Fe.regexp_eatClassSetCharacter=function(e){var t=e.pos;if(e.eat(92))return!(!this.regexp_eatCharacterEscape(e)&&!this.regexp_eatClassSetReservedPunctuator(e)&&(e.eat(98)?(e.lastIntValue=8,0):(e.pos=t,1)));var s=e.current();return!(s<0||s===e.lookahead()&&function(e){return 33===e||e>=35&&e<=38||e>=42&&e<=44||46===e||e>=58&&e<=64||94===e||96===e||126===e}(s)||function(e){return 40===e||41===e||45===e||47===e||e>=91&&e<=93||e>=123&&e<=125}(s)||(e.advance(),e.lastIntValue=s,0))},Fe.regexp_eatClassSetReservedPunctuator=function(e){var t=e.current();return!!function(e){return 33===e||35===e||37===e||38===e||44===e||45===e||e>=58&&e<=62||64===e||96===e||126===e}(t)&&(e.lastIntValue=t,e.advance(),!0)},Fe.regexp_eatClassControlLetter=function(e){var t=e.current();return!(!Pe(t)&&95!==t||(e.lastIntValue=t%32,e.advance(),0))},Fe.regexp_eatHexEscapeSequence=function(e){var t=e.pos;if(e.eat(120)){if(this.regexp_eatFixedHexDigits(e,2))return!0;e.switchU&&e.raise("Invalid escape"),e.pos=t}return!1},Fe.regexp_eatDecimalDigits=function(e){var t=e.pos,s=0;for(e.lastIntValue=0;Pe(s=e.current());)e.lastIntValue=10*e.lastIntValue+(s-48),e.advance();return e.pos!==t},Fe.regexp_eatHexDigits=function(e){var t=e.pos,s=0;for(e.lastIntValue=0;Be(s=e.current());)e.lastIntValue=16*e.lastIntValue+ze(s),e.advance();return e.pos!==t},Fe.regexp_eatLegacyOctalEscapeSequence=function(e){if(this.regexp_eatOctalDigit(e)){var t=e.lastIntValue;if(this.regexp_eatOctalDigit(e)){var s=e.lastIntValue;t<=3&&this.regexp_eatOctalDigit(e)?e.lastIntValue=64*t+8*s+e.lastIntValue:e.lastIntValue=8*t+s}else e.lastIntValue=t;return!0}return!1},Fe.regexp_eatOctalDigit=function(e){var t=e.current();return Ue(t)?(e.lastIntValue=t-48,e.advance(),!0):(e.lastIntValue=0,!1)},Fe.regexp_eatFixedHexDigits=function(e,t){var s=e.pos;e.lastIntValue=0;for(var r=0;r=this.input.length?this.finishToken(b.eof):e.override?e.override(this):void this.readToken(this.fullCharCodeAtPos())},We.readToken=function(e){return c(e,this.options.ecmaVersion>=6)||92===e?this.readWord():this.getTokenFromCode(e)},We.fullCharCodeAtPos=function(){var e=this.input.charCodeAt(this.pos);if(e<=55295||e>=56320)return e;var t=this.input.charCodeAt(this.pos+1);return t<=56319||t>=57344?e:(e<<10)+t-56613888},We.skipBlockComment=function(){var e=this.options.onComment&&this.curPosition(),t=this.pos,s=this.input.indexOf("*/",this.pos+=2);if(-1===s&&this.raise(this.pos-2,"Unterminated comment"),this.pos=s+2,this.options.locations)for(var r=void 0,n=t;(r=A(this.input,n,this.pos))>-1;)++this.curLine,n=this.lineStart=r;this.options.onComment&&this.options.onComment(!0,this.input.slice(t+2,s),t,this.pos,e,this.curPosition())},We.skipLineComment=function(e){for(var t=this.pos,s=this.options.onComment&&this.curPosition(),r=this.input.charCodeAt(this.pos+=e);this.pos8&&e<14||e>=5760&&w.test(String.fromCharCode(e))))break e;++this.pos}}},We.finishToken=function(e,t){this.end=this.pos,this.options.locations&&(this.endLoc=this.curPosition());var s=this.type;this.type=e,this.value=t,this.updateContext(s)},We.readToken_dot=function(){var e=this.input.charCodeAt(this.pos+1);if(e>=48&&e<=57)return this.readNumber(!0);var t=this.input.charCodeAt(this.pos+2);return this.options.ecmaVersion>=6&&46===e&&46===t?(this.pos+=3,this.finishToken(b.ellipsis)):(++this.pos,this.finishToken(b.dot))},We.readToken_slash=function(){var e=this.input.charCodeAt(this.pos+1);return this.exprAllowed?(++this.pos,this.readRegexp()):61===e?this.finishOp(b.assign,2):this.finishOp(b.slash,1)},We.readToken_mult_modulo_exp=function(e){var t=this.input.charCodeAt(this.pos+1),s=1,r=42===e?b.star:b.modulo;return this.options.ecmaVersion>=7&&42===e&&42===t&&(++s,r=b.starstar,t=this.input.charCodeAt(this.pos+2)),61===t?this.finishOp(b.assign,s+1):this.finishOp(r,s)},We.readToken_pipe_amp=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?this.options.ecmaVersion>=12&&61===this.input.charCodeAt(this.pos+2)?this.finishOp(b.assign,3):this.finishOp(124===e?b.logicalOR:b.logicalAND,2):61===t?this.finishOp(b.assign,2):this.finishOp(124===e?b.bitwiseOR:b.bitwiseAND,1)},We.readToken_caret=function(){return 61===this.input.charCodeAt(this.pos+1)?this.finishOp(b.assign,2):this.finishOp(b.bitwiseXOR,1)},We.readToken_plus_min=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?45!==t||this.inModule||62!==this.input.charCodeAt(this.pos+2)||0!==this.lastTokEnd&&!v.test(this.input.slice(this.lastTokEnd,this.pos))?this.finishOp(b.incDec,2):(this.skipLineComment(3),this.skipSpace(),this.nextToken()):61===t?this.finishOp(b.assign,2):this.finishOp(b.plusMin,1)},We.readToken_lt_gt=function(e){var t=this.input.charCodeAt(this.pos+1),s=1;return t===e?(s=62===e&&62===this.input.charCodeAt(this.pos+2)?3:2,61===this.input.charCodeAt(this.pos+s)?this.finishOp(b.assign,s+1):this.finishOp(b.bitShift,s)):33!==t||60!==e||this.inModule||45!==this.input.charCodeAt(this.pos+2)||45!==this.input.charCodeAt(this.pos+3)?(61===t&&(s=2),this.finishOp(b.relational,s)):(this.skipLineComment(4),this.skipSpace(),this.nextToken())},We.readToken_eq_excl=function(e){var t=this.input.charCodeAt(this.pos+1);return 61===t?this.finishOp(b.equality,61===this.input.charCodeAt(this.pos+2)?3:2):61===e&&62===t&&this.options.ecmaVersion>=6?(this.pos+=2,this.finishToken(b.arrow)):this.finishOp(61===e?b.eq:b.prefix,1)},We.readToken_question=function(){var e=this.options.ecmaVersion;if(e>=11){var t=this.input.charCodeAt(this.pos+1);if(46===t){var s=this.input.charCodeAt(this.pos+2);if(s<48||s>57)return this.finishOp(b.questionDot,2)}if(63===t)return e>=12&&61===this.input.charCodeAt(this.pos+2)?this.finishOp(b.assign,3):this.finishOp(b.coalesce,2)}return this.finishOp(b.question,1)},We.readToken_numberSign=function(){var e=35;if(this.options.ecmaVersion>=13&&(++this.pos,c(e=this.fullCharCodeAtPos(),!0)||92===e))return this.finishToken(b.privateId,this.readWord1());this.raise(this.pos,"Unexpected character '"+$(e)+"'")},We.getTokenFromCode=function(e){switch(e){case 46:return this.readToken_dot();case 40:return++this.pos,this.finishToken(b.parenL);case 41:return++this.pos,this.finishToken(b.parenR);case 59:return++this.pos,this.finishToken(b.semi);case 44:return++this.pos,this.finishToken(b.comma);case 91:return++this.pos,this.finishToken(b.bracketL);case 93:return++this.pos,this.finishToken(b.bracketR);case 123:return++this.pos,this.finishToken(b.braceL);case 125:return++this.pos,this.finishToken(b.braceR);case 58:return++this.pos,this.finishToken(b.colon);case 96:if(this.options.ecmaVersion<6)break;return++this.pos,this.finishToken(b.backQuote);case 48:var t=this.input.charCodeAt(this.pos+1);if(120===t||88===t)return this.readRadixNumber(16);if(this.options.ecmaVersion>=6){if(111===t||79===t)return this.readRadixNumber(8);if(98===t||66===t)return this.readRadixNumber(2)}case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return this.readNumber(!1);case 34:case 39:return this.readString(e);case 47:return this.readToken_slash();case 37:case 42:return this.readToken_mult_modulo_exp(e);case 124:case 38:return this.readToken_pipe_amp(e);case 94:return this.readToken_caret();case 43:case 45:return this.readToken_plus_min(e);case 60:case 62:return this.readToken_lt_gt(e);case 61:case 33:return this.readToken_eq_excl(e);case 63:return this.readToken_question();case 126:return this.finishOp(b.prefix,1);case 35:return this.readToken_numberSign()}this.raise(this.pos,"Unexpected character '"+$(e)+"'")},We.finishOp=function(e,t){var s=this.input.slice(this.pos,this.pos+t);return this.pos+=t,this.finishToken(e,s)},We.readRegexp=function(){for(var e,t,s=this.pos;;){this.pos>=this.input.length&&this.raise(s,"Unterminated regular expression");var r=this.input.charAt(this.pos);if(v.test(r)&&this.raise(s,"Unterminated regular expression"),e)e=!1;else{if("["===r)t=!0;else if("]"===r&&t)t=!1;else if("/"===r&&!t)break;e="\\"===r}++this.pos}var n=this.input.slice(s,this.pos);++this.pos;var i=this.pos,a=this.readWord1();this.containsEsc&&this.unexpected(i);var o=this.regexpState||(this.regexpState=new Re(this));o.reset(s,n,a),this.validateRegExpFlags(o),this.validateRegExpPattern(o);var u=null;try{u=new RegExp(n,a)}catch(e){}return this.finishToken(b.regexp,{pattern:n,flags:a,value:u})},We.readInt=function(e,t,s){for(var r=this.options.ecmaVersion>=12&&void 0===t,n=s&&48===this.input.charCodeAt(this.pos),i=this.pos,a=0,o=0,u=0,l=null==t?1/0:t;u=97?h-97+10:h>=65?h-65+10:h>=48&&h<=57?h-48:1/0)>=e)break;o=h,a=a*e+c}}return r&&95===o&&this.raiseRecoverable(this.pos-1,"Numeric separator is not allowed at the last of digits"),this.pos===i||null!=t&&this.pos-i!==t?null:a},We.readRadixNumber=function(e){var t=this.pos;this.pos+=2;var s=this.readInt(e);return null==s&&this.raise(this.start+2,"Expected number in radix "+e),this.options.ecmaVersion>=11&&110===this.input.charCodeAt(this.pos)?(s=je(this.input.slice(t,this.pos)),++this.pos):c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number"),this.finishToken(b.num,s)},We.readNumber=function(e){var t=this.pos;e||null!==this.readInt(10,void 0,!0)||this.raise(t,"Invalid number");var s=this.pos-t>=2&&48===this.input.charCodeAt(t);s&&this.strict&&this.raise(t,"Invalid number");var r=this.input.charCodeAt(this.pos);if(!s&&!e&&this.options.ecmaVersion>=11&&110===r){var n=je(this.input.slice(t,this.pos));return++this.pos,c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number"),this.finishToken(b.num,n)}s&&/[89]/.test(this.input.slice(t,this.pos))&&(s=!1),46!==r||s||(++this.pos,this.readInt(10),r=this.input.charCodeAt(this.pos)),69!==r&&101!==r||s||(43!==(r=this.input.charCodeAt(++this.pos))&&45!==r||++this.pos,null===this.readInt(10)&&this.raise(t,"Invalid number")),c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number");var i,a=(i=this.input.slice(t,this.pos),s?parseInt(i,8):parseFloat(i.replace(/_/g,"")));return this.finishToken(b.num,a)},We.readCodePoint=function(){var e;if(123===this.input.charCodeAt(this.pos)){this.options.ecmaVersion<6&&this.unexpected();var t=++this.pos;e=this.readHexChar(this.input.indexOf("}",this.pos)-this.pos),++this.pos,e>1114111&&this.invalidStringToken(t,"Code point out of bounds")}else e=this.readHexChar(4);return e},We.readString=function(e){for(var t="",s=++this.pos;;){this.pos>=this.input.length&&this.raise(this.start,"Unterminated string constant");var r=this.input.charCodeAt(this.pos);if(r===e)break;92===r?(t+=this.input.slice(s,this.pos),t+=this.readEscapedChar(!1),s=this.pos):8232===r||8233===r?(this.options.ecmaVersion<10&&this.raise(this.start,"Unterminated string constant"),++this.pos,this.options.locations&&(this.curLine++,this.lineStart=this.pos)):(T(r)&&this.raise(this.start,"Unterminated string constant"),++this.pos)}return t+=this.input.slice(s,this.pos++),this.finishToken(b.string,t)};var qe={};We.tryReadTemplateToken=function(){this.inTemplateElement=!0;try{this.readTmplToken()}catch(e){if(e!==qe)throw e;this.readInvalidTemplateToken()}this.inTemplateElement=!1},We.invalidStringToken=function(e,t){if(this.inTemplateElement&&this.options.ecmaVersion>=9)throw qe;this.raise(e,t)},We.readTmplToken=function(){for(var e="",t=this.pos;;){this.pos>=this.input.length&&this.raise(this.start,"Unterminated template");var s=this.input.charCodeAt(this.pos);if(96===s||36===s&&123===this.input.charCodeAt(this.pos+1))return this.pos!==this.start||this.type!==b.template&&this.type!==b.invalidTemplate?(e+=this.input.slice(t,this.pos),this.finishToken(b.template,e)):36===s?(this.pos+=2,this.finishToken(b.dollarBraceL)):(++this.pos,this.finishToken(b.backQuote));if(92===s)e+=this.input.slice(t,this.pos),e+=this.readEscapedChar(!0),t=this.pos;else if(T(s)){switch(e+=this.input.slice(t,this.pos),++this.pos,s){case 13:10===this.input.charCodeAt(this.pos)&&++this.pos;case 10:e+="\n";break;default:e+=String.fromCharCode(s)}this.options.locations&&(++this.curLine,this.lineStart=this.pos),t=this.pos}else++this.pos}},We.readInvalidTemplateToken=function(){for(;this.pos=48&&t<=55){var r=this.input.substr(this.pos-1,3).match(/^[0-7]+/)[0],n=parseInt(r,8);return n>255&&(r=r.slice(0,-1),n=parseInt(r,8)),this.pos+=r.length-1,t=this.input.charCodeAt(this.pos),"0"===r&&56!==t&&57!==t||!this.strict&&!e||this.invalidStringToken(this.pos-1-r.length,e?"Octal literal in template string":"Octal literal in strict mode"),String.fromCharCode(n)}return T(t)?(this.options.locations&&(this.lineStart=this.pos,++this.curLine),""):String.fromCharCode(t)}},We.readHexChar=function(e){var t=this.pos,s=this.readInt(16,e);return null===s&&this.invalidStringToken(t,"Bad character escape sequence"),s},We.readWord1=function(){this.containsEsc=!1;for(var e="",t=!0,s=this.pos,r=this.options.ecmaVersion>=6;this.pos{var s=class{constructor(e,t){this.value=e,Array.isArray(t)?this.size=t:(this.size=new Int32Array(3),t.z?this.size=new Int32Array([t.x,t.y,t.z]):t.y?this.size=new Int32Array([t.x,t.y]):this.size=new Int32Array([t.x]));const[s,r,n]=this.size;if(n){if(this.value.length!==s*r*n)throw new Error(`Input size ${this.value.length} does not match ${s} * ${r} * ${n} = ${r*s*n}`)}else if(r){if(this.value.length!==s*r)throw new Error(`Input size ${this.value.length} does not match ${s} * ${r} = ${r*s}`)}else if(this.value.length!==s)throw new Error(`Input size ${this.value.length} does not match ${s}`)}toArray(){const{utils:e}=i(),[t,s,r]=this.size;return r?e.erectMemoryOptimized3DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,s,r):s?e.erectMemoryOptimized2DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,s):this.value}};t.exports={Input:s,input:function(e,t){return new s(e,t)}}}),n=e((e,t)=>{t.exports={Texture:class{constructor(e){const{texture:t,size:s,dimensions:r,output:n,context:i,type:a="NumberTexture",kernel:o,internalFormat:u,textureFormat:l}=e;if(!n)throw new Error('settings property "output" required.');if(!i)throw new Error('settings property "context" required.');if(!t)throw new Error('settings property "texture" required.');if(!o)throw new Error('settings property "kernel" required.');this.texture=t,t._refs?t._refs++:t._refs=1,this.size=s,this.dimensions=r,this.output=n,this.context=i,this.kernel=o,this.type=a,this._deleted=!1,this.internalFormat=u,this.textureFormat=l}toArray(){throw new Error(`Not implemented on ${this.constructor.name}`)}clone(){throw new Error(`Not implemented on ${this.constructor.name}`)}delete(){throw new Error(`Not implemented on ${this.constructor.name}`)}clear(){throw new Error(`Not implemented on ${this.constructor.name}`)}}}}),i=e((e,t)=>{const i=s(),{Input:a}=r(),{Texture:o}=n(),u=/function ([^(]*)/,l=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,h=/([^\s,]+)/g,c={systemEndianness:()=>m,getSystemEndianness(){const e=new ArrayBuffer(4),t=new Uint32Array(e),s=new Uint8Array(e);if(t[0]=3735928559,239===s[0])return"LE";if(222===s[0])return"BE";throw new Error("unknown endianness")},isFunction:e=>"function"==typeof e,isFunctionString:e=>"string"==typeof e&&"function"===e.slice(0,8).toLowerCase(),getFunctionNameFromString(e){const t=u.exec(e);return t&&0!==t.length?t[1].trim():null},getFunctionBodyFromString:e=>e.substring(e.indexOf("{")+1,e.lastIndexOf("}")),getArgumentNamesFromString(e){const t=e.replace(l,"");let s=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(h);return null===s&&(s=[]),s},clone(e){if(null===e||"object"!=typeof e||e.hasOwnProperty("isActiveClone"))return e;const t=e.constructor();for(let s in e)Object.prototype.hasOwnProperty.call(e,s)&&(e.isActiveClone=null,t[s]=c.clone(e[s]),delete e.isActiveClone);return t},isArray:e=>!isNaN(e.length),typeFitsValue(e,t){if("string"!=typeof e||null==t)return!0;if(t.type)return!0;switch(e){case"Input":return t instanceof a;case"Boolean":return"boolean"==typeof t;case"Number":case"Integer":case"Float":return"number"==typeof t}return-1!==e.indexOf("Texture")?Boolean(t.type):0!==e.indexOf("Array")||c.isArray(t)},getVariableType(e,t){if(c.isArray(e))return e.length>0&&"IMG"===e[0].nodeName?"HTMLImageArray":"Array";switch(e.constructor){case Boolean:return"Boolean";case Number:return t&&Number.isInteger(e)?"Integer":"Float";case o:return e.type;case a:return"Input"}if("nodeName"in e)switch(e.nodeName){case"IMG":case"CANVAS":return"HTMLImage";case"VIDEO":return"HTMLVideo"}else{if(e.hasOwnProperty("type"))return e.type;if("undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return"OffscreenCanvas";if("undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap)return"ImageBitmap";if("undefined"!=typeof ImageData&&e instanceof ImageData)return"ImageData"}return"Unknown"},getKernelTextureSize(e,t){let[s,r,n]=t,i=(s||1)*(r||1)*(n||1);return e.optimizeFloatMemory&&"single"===e.precision&&(s=i=Math.ceil(i/4)),r>1&&s*r===i?new Int32Array([s,r]):c.closestSquareDimensions(i)},closestSquareDimensions(e){const t=Math.sqrt(e);let s=Math.ceil(t),r=Math.floor(t);for(;s*rMath.floor((e+t-1)/t)*t,getDimensions(e,t){let s;if(c.isArray(e)){const t=[];let r=e;for(;c.isArray(r);)t.push(r.length),r=r[0];s=t.reverse()}else if(e instanceof o)s=e.output;else{if(!(e instanceof a))throw new Error(`Unknown dimensions of ${e}`);s=e.size}if(t)for(s=Array.from(s);s.length<3;)s.push(1);return new Int32Array(s)},flatten2dArrayTo(e,t){let s=0;for(let r=0;re.length>0?e.join(";\n")+";\n":"\n",warnDeprecated(e,t,s){s?console.warn(`You are using a deprecated ${e} "${t}". It has been replaced with "${s}". Fixing, but please upgrade as it will soon be removed.`):console.warn(`You are using a deprecated ${e} "${t}". It has been removed. Fixing, but please upgrade as it will soon be removed.`)},flipPixels:(e,t,s)=>{const r=s/2|0,n=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee.subarray(0,t),erect2DPackedFloat:(e,t,s)=>{const r=new Array(s);for(let n=0;n{const n=new Array(r);for(let i=0;ie.subarray(0,t),erectMemoryOptimized2DFloat:(e,t,s)=>{const r=new Array(s);for(let n=0;n{const n=new Array(r);for(let i=0;i{const s=new Float32Array(t);let r=0;for(let n=0;n{const r=new Array(s);let n=0;for(let i=0;i{const n=new Array(r);let i=0;for(let a=0;a{const s=new Array(t),r=4*t;let n=0;for(let t=0;t{const r=new Array(s),n=4*t;for(let i=0;i{const n=4*t,i=new Array(r);for(let a=0;a{const s=new Array(t),r=4*t;let n=0;for(let t=0;t{const r=4*t,n=new Array(s);for(let i=0;i{const n=4*t,i=new Array(r);for(let a=0;a{const s=new Array(e),r=4*t;let n=0;for(let t=0;t{const r=4*t,n=new Array(s);for(let i=0;i{const n=4*t,i=new Array(r);for(let a=0;a{const{findDependency:s,thisLookup:r,doNotDefine:n}=t;let a=t.flattened;a||(a=t.flattened={});const o=i.parse(e,{ecmaVersion:2020}),u=[];let l=0;const h=function e(t){if(Array.isArray(t)){const s=[];for(let r=0;rnull!==e);return n.length<1?"":`${t.kind} ${n.join(",")}`;case"VariableDeclarator":return t.init?t.init.object&&"ThisExpression"===t.init.object.type?r(t.init.property.name,!0)?`${t.id.name} = ${e(t.init)}`:null:`${t.id.name} = ${e(t.init)}`:t.id.name;case"CallExpression":if("subarray"===t.callee.property.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("gl"===t.callee.object.name||"context"===t.callee.object.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("ThisExpression"===t.callee.object.type)return u.push(s("this",t.callee.property.name)),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;if(t.callee.object.name){const r=s(t.callee.object.name,t.callee.property.name);return null===r?`${t.callee.object.name}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`:(u.push(r),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`)}if("MemberExpression"===t.callee.object.type)return`${e(t.callee.object)}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;throw new Error("unknown ast.callee");case"ReturnStatement":return`return ${e(t.argument)}`;case"BinaryExpression":return`(${e(t.left)}${t.operator}${e(t.right)})`;case"UnaryExpression":return t.prefix?`${t.operator} ${e(t.argument)}`:`${e(t.argument)} ${t.operator}`;case"ExpressionStatement":return`${e(t.expression)}`;case"SequenceExpression":return`(${e(t.expressions)})`;case"ArrowFunctionExpression":return`(${t.params.map(e).join(", ")}) => ${e(t.body)}`;case"Literal":return t.raw;case"Identifier":return t.name;case"MemberExpression":return"ThisExpression"===t.object.type?r(t.property.name):t.computed?`${e(t.object)}[${e(t.property)}]`:e(t.object)+"."+e(t.property);case"ThisExpression":return"this";case"NewExpression":return`new ${e(t.callee)}(${t.arguments.map(t=>e(t)).join(", ")})`;case"ForStatement":return`for (${e(t.init)};${e(t.test)};${e(t.update)}) ${e(t.body)}`;case"AssignmentExpression":return`${e(t.left)}${t.operator}${e(t.right)}`;case"UpdateExpression":return`${e(t.argument)}${t.operator}`;case"IfStatement":{const s=e(t.consequent);if(!t.alternate)return`if (${e(t.test)}) ${s}`;const r="BlockStatement"===t.consequent.type?"":";";return`if (${e(t.test)}) ${s}${r} else ${e(t.alternate)}`}case"ThrowStatement":return`throw ${e(t.argument)}`;case"ObjectPattern":return t.properties.map(e).join(", ");case"ArrayPattern":return t.elements.map(e).join(", ");case"DebuggerStatement":return"debugger;";case"ConditionalExpression":return`${e(t.test)}?${e(t.consequent)}:${e(t.alternate)}`;case"Property":if("init"===t.kind)return e(t.key)}throw new Error(`unhandled ast.type of ${t.type}`)}(o);if(u.length>0){const e=[];for(let s=0;s{if("VariableDeclaration"!==e.type)throw new Error('Ast is not of type "VariableDeclaration"');const t=[];for(let s=0;s{const s=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].r},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),r=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].g},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),n=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].b},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),i=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].a},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),a=[s(t),r(t),n(t),i(t)];return a.rKernel=s,a.gKernel=r,a.bKernel=n,a.aKernel=i,a.gpu=e,a},splitRGBAToCanvases:(e,t,s,r)=>{const n=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(t.r/255,0,0,255)},{output:[s,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});n(t);const i=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,t.g/255,0,255)},{output:[s,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});i(t);const a=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,0,t.b/255,255)},{output:[s,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});a(t);const o=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(255,255,255,t.a/255)},{output:[s,r],graphical:!0,argumentTypes:{v:"Array2D(4)"}});return o(t),[n.canvas,i.canvas,a.canvas,o.canvas]},getMinifySafeName:e=>{try{const{init:t}=i.parse(`const value = ${e.toString()}`,{ecmaVersion:2020}).body[0].declarations[0];return t.body.name||t.body.body[0].argument.name}catch(e){throw new Error("Unrecognized function type. Please use `() => yourFunctionVariableHere` or function() { return yourFunctionVariableHere; }")}},sanitizeName:function(e){return p.test(e)&&(e=e.replace(p,"S_S")),d.test(e)?e=e.replace(d,"U_U"):f.test(e)&&(e=e.replace(f,"u_u")),e}},p=/\$/,d=/__/,f=/_/,m=c.getSystemEndianness();t.exports={utils:c}}),a=e((e,t)=>{const{utils:s}=i(),{Input:n}=r();t.exports={Kernel:class{static get isSupported(){throw new Error(`"isSupported" not implemented on ${this.name}`)}static isContextMatch(e){throw new Error(`"isContextMatch" not implemented on ${this.name}`)}static getFeatures(){throw new Error(`"getFeatures" not implemented on ${this.name}`)}static destroyContext(e){throw new Error(`"destroyContext" called on ${this.name}`)}static nativeFunctionArguments(){throw new Error(`"nativeFunctionArguments" called on ${this.name}`)}static nativeFunctionReturnType(){throw new Error(`"nativeFunctionReturnType" called on ${this.name}`)}static combineKernels(){throw new Error(`"combineKernels" called on ${this.name}`)}constructor(e,t){if("object"!=typeof e){if("string"!=typeof e)throw new Error("source not a string");if(!s.isFunctionString(e))throw new Error("source not a function string")}this.useLegacyEncoder=!1,this.fallbackRequested=!1,this.fallbackReason=null,this.onRequestFallback=null,this.onRequestSwitchKernel=null,this.argumentNames="string"==typeof e?s.getArgumentNamesFromString(e):null,this.argumentTypes=null,this.declaredArgumentTypes=null,this.argumentSizes=null,this.argumentBitRatios=null,this.kernelArguments=null,this.kernelConstants=null,this.forceUploadKernelConstants=null,this.source=e,this.output=null,this.debug=!1,this.graphical=!1,this.loopMaxIterations=0,this.constants=null,this.constantTypes=null,this.constantBitRatios=null,this.dynamicArguments=!1,this.dynamicOutput=!1,this.canvas=null,this.context=null,this.checkContext=null,this.gpu=null,this.functions=null,this.nativeFunctions=null,this.injectedNative=null,this.subKernels=null,this.validate=!0,this.immutable=!1,this.pipeline=!1,this.asyncMode=!1,this.precision=null,this.tactic=null,this.plugins=null,this.returnType=null,this.leadingReturnStatement=null,this.followingReturnStatement=null,this.optimizeFloatMemory=null,this.strictIntegers=!1,this.fixIntegerDivisionAccuracy=null,this.randomSeed=null,this.built=!1,this.signature=null,this.switchingKernels=null}mergeSettings(e){for(let t in e)if(e.hasOwnProperty(t)&&this.hasOwnProperty(t)){switch(t){case"argumentTypes":this.argumentTypes=e[t],e[t]&&(this.declaredArgumentTypes=Array.isArray(e[t])?e[t].slice():e[t]);continue;case"output":if(!Array.isArray(e.output)){this.setOutput(e.output);continue}break;case"functions":this.functions=[];for(let t=0;te.name):null,returnType:this.returnType}}}buildSignature(e){const t=this.constructor;this.signature=t.getSignature(this,t.getArgumentTypes(this,e))}static getArgumentTypes(e,t){const r=new Array(t.length);for(let n=0;nt.argumentTypes[e])||[];const i=Object.keys(t.argumentTypes);if(i.length>0&&e.length>0&&n.every(e=>void 0===e))throw new Error(`argumentTypes keys [${i.join(", ")}] match none of the function's parameters [${e.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${i.map(e=>t.argumentTypes[e]).join("', '")}']`)}else n=t.argumentTypes||[];return{name:t.name||s.getFunctionNameFromString(r)||("function"==typeof e&&e.name?e.name:null),source:r,argumentTypes:n,returnType:t.returnType||null}}onActivate(e){}switchKernels(e){this.switchingKernels?this.switchingKernels.push(e):this.switchingKernels=[e]}resetSwitchingKernels(){const e=this.switchingKernels;return this.switchingKernels=null,e}checkArgumentTypes(e){if(!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let r=0;r{t.exports={FunctionBuilder:class e{static fromKernel(t,s,r){const{kernelArguments:n,kernelConstants:i,argumentNames:a,argumentSizes:o,argumentBitRatios:u,constants:l,constantBitRatios:h,debug:c,loopMaxIterations:p,nativeFunctions:d,output:f,optimizeFloatMemory:m,precision:g,plugins:y,source:x,subKernels:b,functions:v,leadingReturnStatement:S,followingReturnStatement:T,dynamicArguments:A,dynamicOutput:w}=t,_=new Array(n.length),E={};for(let e=0;ez.needsArgumentType(e,t),k=(e,t,s)=>{z.assignArgumentType(e,t,s)},C=(e,t,s)=>z.lookupReturnType(e,t,s),L=e=>z.lookupFunctionArgumentTypes(e),D=(e,t)=>z.lookupFunctionArgumentName(e,t),F=(e,t)=>z.lookupFunctionArgumentBitRatio(e,t),$=(e,t,s,r)=>{z.assignArgumentType(e,t,s,r)},R=(e,t,s,r)=>{z.assignArgumentBitRatio(e,t,s,r)},N=(e,t,s)=>{z.trackFunctionCall(e,t,s)},M=(e,t)=>{const r=[];for(let t=0;tnew s(e.source,{name:e.name||void 0,returnType:e.returnType,argumentTypes:e.argumentTypes,output:f,plugins:y,constants:l,constantTypes:E,constantBitRatios:h,optimizeFloatMemory:m,precision:g,lookupReturnType:C,lookupFunctionArgumentTypes:L,lookupFunctionArgumentName:D,lookupFunctionArgumentBitRatio:F,needsArgumentType:I,assignArgumentType:k,triggerImplyArgumentType:$,triggerImplyArgumentBitRatio:R,onFunctionCall:N,onNestedFunction:M})));let B=null;b&&(B=b.map(e=>{const{name:t,source:r}=e;return new s(r,Object.assign({},G,{name:t,isSubKernel:!0,isRootKernel:!1}))}));const z=new e({kernel:t,rootNode:V,functionNodes:P,nativeFunctions:d,subKernelNodes:B});return z}constructor(e){if(e=e||{},this.kernel=e.kernel,this.rootNode=e.rootNode,this.functionNodes=e.functionNodes||[],this.subKernelNodes=e.subKernelNodes||[],this.nativeFunctions=e.nativeFunctions||[],this.functionMap={},this.nativeFunctionNames=[],this.lookupChain=[],this.functionNodeDependencies={},this.functionCalls={},this.rootNode&&(this.functionMap.kernel=this.rootNode),this.functionNodes)for(let e=0;e-1){const s=t.indexOf(e);if(-1===s)t.push(e);else{const e=t.splice(s,1)[0];t.push(e)}return t}const s=this.functionMap[e];if(s){const r=t.indexOf(e);if(-1===r){t.push(e),s.toString();for(let e=0;e-1){t.push(this.nativeFunctions[n].source);continue}const i=this.functionMap[r];i&&t.push(i.toString())}return t}toJSON(){return this.traceFunctionCalls(this.rootNode.name).reverse().map(e=>{const t=this.nativeFunctions.indexOf(e);if(t>-1)return{name:e,source:this.nativeFunctions[t].source};if(this.functionMap[e])return this.functionMap[e].toJSON();throw new Error(`function ${e} not found`)})}fromJSON(e,t){this.functionMap={};for(let s=0;s0){const n=t.arguments;for(let t=0;t{const{utils:s}=i();function r(e){return e.length>0?e[e.length-1]:null}const n="trackIdentifiers",a="memberExpression",o="inForLoopInit";t.exports={FunctionTracer:class{constructor(e){this.runningContexts=[],this.functionContexts=[],this.contexts=[],this.functionCalls=[],this.declarations=[],this.identifiers=[],this.functions=[],this.returnStatements=[],this.trackedIdentifiers=null,this.states=[],this.newFunctionContext(),this.scan(e)}isState(e){return this.states[this.states.length-1]===e}hasState(e){return this.states.indexOf(e)>-1}pushState(e){this.states.push(e)}popState(e){if(!this.isState(e))throw new Error(`Cannot pop the non-active state "${e}"`);this.states.pop()}get currentFunctionContext(){return r(this.functionContexts)}get currentContext(){return r(this.runningContexts)}newFunctionContext(){const e={"@contextType":"function"};this.contexts.push(e),this.functionContexts.push(e)}newContext(e){const t=Object.assign({"@contextType":"const/let"},this.currentContext);this.contexts.push(t),this.runningContexts.push(t),e();const{currentFunctionContext:s}=this;for(const e in s)s.hasOwnProperty(e)&&!t.hasOwnProperty(e)&&(t[e]=s[e]);return this.runningContexts.pop(),t}useFunctionContext(e){const t=r(this.functionContexts);this.runningContexts.push(t),e(),this.runningContexts.pop()}getIdentifiers(e){const t=this.trackedIdentifiers=[];return this.pushState(n),e(),this.trackedIdentifiers=null,this.popState(n),t}getDeclaration(e){const{currentContext:t,currentFunctionContext:s,runningContexts:r}=this,n=t[e]||s[e]||null;if(!n&&t===s&&r.length>0){const t=r[r.length-2];if(t[e])return t[e]}return n}scan(e){if(e)if(Array.isArray(e))for(let t=0;t{this.scan(e.body)});break;case"BlockStatement":this.newContext(()=>{this.scan(e.body)});break;case"AssignmentExpression":case"LogicalExpression":case"BinaryExpression":this.scan(e.left),this.scan(e.right);break;case"UpdateExpression":if("++"===e.operator){const t=this.getDeclaration(e.argument.name);t&&(t.suggestedType="Integer")}this.scan(e.argument);break;case"UnaryExpression":this.scan(e.argument);break;case"VariableDeclaration":"var"===e.kind?this.useFunctionContext(()=>{e.declarations=s.normalizeDeclarations(e),this.scan(e.declarations)}):(e.declarations=s.normalizeDeclarations(e),this.scan(e.declarations));break;case"VariableDeclarator":{const{currentContext:t}=this,s=this.hasState(o),r={ast:e,context:t,name:e.id.name,origin:"declaration",inForLoopInit:s,inForLoopTest:null,assignable:t===this.currentFunctionContext||!s&&!t.hasOwnProperty(e.id.name),suggestedType:null,valueType:null,dependencies:null,isSafe:null};t[e.id.name]||(t[e.id.name]=r),this.declarations.push(r),this.scan(e.id),this.scan(e.init);break}case"FunctionExpression":case"FunctionDeclaration":0===this.runningContexts.length?this.scan(e.body):this.functions.push(e);break;case"IfStatement":this.scan(e.test),this.scan(e.consequent),e.alternate&&this.scan(e.alternate);break;case"ForStatement":{let t;const s=this.newContext(()=>{this.pushState(o),this.scan(e.init),this.popState(o),t=this.getIdentifiers(()=>{this.scan(e.test)}),this.scan(e.update),this.newContext(()=>{this.scan(e.body)})});if(t)for(const e in s)"@contextType"!==e&&t.indexOf(e)>-1&&(s[e].inForLoopTest=!0);break}case"DoWhileStatement":case"WhileStatement":this.newContext(()=>{this.scan(e.body),this.scan(e.test)});break;case"Identifier":this.isState(n)&&this.trackedIdentifiers.push(e.name),this.identifiers.push({context:this.currentContext,declaration:this.getDeclaration(e.name),ast:e});break;case"ReturnStatement":this.returnStatements.push(e),this.scan(e.argument);break;case"MemberExpression":this.pushState(a),this.scan(e.object),this.scan(e.property),this.popState(a);break;case"ExpressionStatement":this.scan(e.expression);break;case"SequenceExpression":this.scan(e.expressions);break;case"CallExpression":this.functionCalls.push({context:this.currentContext,ast:e}),this.scan(e.arguments);break;case"ArrayExpression":this.scan(e.elements);break;case"ConditionalExpression":this.scan(e.test),this.scan(e.alternate),this.scan(e.consequent);break;case"SwitchStatement":this.scan(e.discriminant),this.scan(e.cases);break;case"SwitchCase":this.scan(e.test),this.scan(e.consequent);break;case"ThisExpression":case"Literal":case"DebuggerStatement":case"EmptyStatement":case"BreakStatement":case"ContinueStatement":break;default:throw new Error(`unhandled type "${e.type}"`)}}}}}),l=e((e,t)=>{const r=s(),{utils:n}=i(),{FunctionTracer:a}=u(),o=["E","PI","SQRT2","SQRT1_2","LN2","LN10","LOG2E","LOG10E"],l=["abs","acos","acosh","asin","asinh","atan","atan2","atanh","cbrt","ceil","clz32","cos","cosh","expm1","exp","floor","fround","imul","log","log2","log10","log1p","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc"],h=["value","value[]","value[][]","value[][][]","value[][][][]","value.value","value.thread.value","this.thread.value","this.output.value","this.constants.value","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]","fn()[]","fn()[][]","fn()[][][]","[][]"];const c={Number:"Number",Float:"Float",Integer:"Integer",Array:"Number","Array(2)":"Number","Array(3)":"Number","Array(4)":"Number","Matrix(2)":"Number","Matrix(3)":"Number","Matrix(4)":"Number",Array2D:"Number",Array3D:"Number",Input:"Number",HTMLCanvas:"Array(4)",OffscreenCanvas:"Array(4)",HTMLImage:"Array(4)",ImageBitmap:"Array(4)",ImageData:"Array(4)",HTMLVideo:"Array(4)",HTMLImageArray:"Array(4)",NumberTexture:"Number",MemoryOptimizedNumberTexture:"Number","Array1D(2)":"Array(2)","Array1D(3)":"Array(3)","Array1D(4)":"Array(4)","Array2D(2)":"Array(2)","Array2D(3)":"Array(3)","Array2D(4)":"Array(4)","Array3D(2)":"Array(2)","Array3D(3)":"Array(3)","Array3D(4)":"Array(4)","ArrayTexture(1)":"Number","ArrayTexture(2)":"Array(2)","ArrayTexture(3)":"Array(3)","ArrayTexture(4)":"Array(4)"};let p=536870912;function d(e,t){return e.start=p++,e.end=p++,t&&t.loc&&(e.loc=t.loc),e}function f(e,t){return e&&e.body&&"BlockStatement"===e.body.type?(m(e.body,t),e):e}function m(e,t){e.body=g(e.body,t)}function g(e,t){const s=[];for(let r=0;r{if(!e||"object"!=typeof e||s)return e;if(Array.isArray(e))return e.map(r);switch(e.type){case"ContinueStatement":return e.label?(s=!0,e):d({type:"BlockStatement",body:[...T(t),e]},e);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionExpression":case"FunctionDeclaration":case"ArrowFunctionExpression":default:return e;case"IfStatement":return e.consequent=r(e.consequent),e.alternate&&(e.alternate=r(e.alternate)),e;case"BlockStatement":return e.body=e.body.map(r),e;case"SwitchStatement":for(let t=0;t0?(s.push(e),s):[e]}case"WhileStatement":case"DoWhileStatement":return e.body&&(e.body=x(e.body,t)),[e];case"SwitchStatement":for(let s=0;s0&&this.argumentTypes.length!==this.argumentNames.length)throw new Error(`argumentTypes count of ${this.argumentTypes.length} exceeds ${this.argumentNames.length}`);if(this.output.length<1)throw new Error("this.output is not big enough")}isIdentifierConstant(e){return!!this.constants&&this.constants.hasOwnProperty(e)}isInput(e){return"Input"===this.argumentTypes[this.argumentNames.indexOf(e)]}pushState(e){this.states.push(e)}popState(e){if(this.state!==e)throw new Error(`Cannot popState ${e} when in ${this.state}`);this.states.pop()}isState(e){return this.state===e}get state(){return this.states[this.states.length-1]}astMemberExpressionUnroll(e){if("Identifier"===e.type)return e.name;if("ThisExpression"===e.type)return"this";if("MemberExpression"===e.type&&e.object&&e.property)return e.object.hasOwnProperty("name")&&"Math"!==e.object.name?this.astMemberExpressionUnroll(e.property):this.astMemberExpressionUnroll(e.object)+"."+this.astMemberExpressionUnroll(e.property);if(e.hasOwnProperty("expressions")){const t=e.expressions[0];if("Literal"===t.type&&0===t.value&&2===e.expressions.length)return this.astMemberExpressionUnroll(e.expressions[1])}throw this.astErrorOutput("Unknown astMemberExpressionUnroll",e)}get requiresSequenceFreeForInit(){return!1}getJsAST(e){if(this.ast)return this.ast;if("object"==typeof this.source)return f(this.source,this.requiresSequenceFreeForInit),this.traceFunctionAST(this.source),this.ast=this.source;if(null===(e=e||r))throw new Error("Missing JS to AST parser");const t=Object.freeze(e.parse(`const parser_${this.name} = ${this.source};`,{locations:!0,ecmaVersion:2020})),s=t.body[0].declarations[0].init;if(f(s,this.requiresSequenceFreeForInit),this.traceFunctionAST(s),!t)throw new Error("Failed to parse JS code");return this.ast=s}getAssignedArguments(){if(this._assignedArguments)return this._assignedArguments;const e=new Set,t=new Set,s=this.argumentNames||[],r=n=>{if(n&&"object"==typeof n)if(Array.isArray(n))for(const e of n)r(e);else{"AssignmentExpression"===n.type&&"Identifier"===n.left.type&&-1!==s.indexOf(n.left.name)&&e.add(n.left.name),"UpdateExpression"===n.type&&"Identifier"===n.argument.type&&-1!==s.indexOf(n.argument.name)&&e.add(n.argument.name),"VariableDeclarator"===n.type&&"Identifier"===n.id.type&&-1!==s.indexOf(n.id.name)&&t.add(n.id.name);for(const e in n){if("loc"===e||"range"===e||"parent"===e)continue;const t=n[e];t&&"object"==typeof t&&r(t)}}};r(this.getJsAST());for(const s of t)e.delete(s);return this._assignedArguments=e}traceFunctionAST(e){const{contexts:t,declarations:s,functions:r,identifiers:n,functionCalls:i}=new a(e);this.contexts=t,this.identifiers=n,this.functionCalls=i,this.functions=r;for(let e=0;e":case"<":return"Boolean";case"&":case"|":case"^":case"<<":case">>":case">>>":return"Integer"}const s=this.getType(e.left);if(this.isState("skip-literal-correction"))return s;if("LiteralInteger"===s){const t=this.getType(e.right);return"LiteralInteger"===t?e.left.value%1==0?"Integer":"Float":t}if("Integer"===s){const t=this.getType(e.right);if("Number"===t||"Float"===t)return t}return c[s]||s;case"UpdateExpression":case"ReturnStatement":return this.getType(e.argument);case"UnaryExpression":return"~"===e.operator?"Integer":this.getType(e.argument);case"VariableDeclaration":{const t=e.declarations;let s;for(let e=0;ee.isSafe)}getDependencies(e,t,s){if(t||(t=[]),!e)return null;if(Array.isArray(e)){for(let r=0;r-1/0&&e.value<1/0&&!isNaN(e.value))});break;case"VariableDeclarator":return this.getDependencies(e.init,t,s);case"Identifier":const r=this.getDeclaration(e);if(r)t.push({name:e.name,origin:"declaration",isSafe:!s&&this.isSafeDependencies(r.dependencies)});else if(this.argumentNames.indexOf(e.name)>-1)t.push({name:e.name,origin:"argument",isSafe:!1});else if(this.strictTypingChecking)throw new Error(`Cannot find identifier origin "${e.name}"`);break;case"FunctionDeclaration":return this.getDependencies(e.body.body[e.body.body.length-1],t,s);case"ReturnStatement":return this.getDependencies(e.argument,t);case"BinaryExpression":case"LogicalExpression":return s="/"===e.operator||"*"===e.operator,this.getDependencies(e.left,t,s),this.getDependencies(e.right,t,s),t;case"UnaryExpression":case"UpdateExpression":return this.getDependencies(e.argument,t,s);case"VariableDeclaration":return this.getDependencies(e.declarations,t,s);case"ArrayExpression":return t.push({origin:"declaration",isSafe:!0}),t;case"CallExpression":return t.push({origin:"function",isSafe:!0}),t;case"MemberExpression":const n=this.getMemberExpressionDetails(e);switch(n.signature){case"value[]":this.getDependencies(e.object,t,s);break;case"value[][]":this.getDependencies(e.object.object,t,s);break;case"value[][][]":this.getDependencies(e.object.object.object,t,s);break;case"this.output.value":this.dynamicOutput&&t.push({name:n.name,origin:"output",isSafe:!1})}if(n)return n.property&&this.getDependencies(n.property,t,s),n.xProperty&&this.getDependencies(n.xProperty,t,s),n.yProperty&&this.getDependencies(n.yProperty,t,s),n.zProperty&&this.getDependencies(n.zProperty,t,s),t;case"SequenceExpression":return this.getDependencies(e.expressions,t,s);default:throw this.astErrorOutput(`Unhandled type ${e.type} in getDependencies`,e)}return t}getVariableSignature(e,t){if(!this.isAstVariable(e))throw new Error(`ast of type "${e.type}" is not a variable signature`);if("Identifier"===e.type)return"value";const s=[];for(;e;)e.computed?s.push("[]"):"ThisExpression"===e.type?s.unshift("this"):e.property&&e.property.name?"x"===e.property.name||"y"===e.property.name||"z"===e.property.name?s.unshift(t?"."+e.property.name:".value"):"constants"===e.property.name||"thread"===e.property.name||"output"===e.property.name?s.unshift("."+e.property.name):s.unshift(t?"."+e.property.name:".value"):e.name?s.unshift(t?e.name:"value"):e.callee&&e.callee.name?s.unshift(t?e.callee.name+"()":"fn()"):e.elements?s.unshift("[]"):s.unshift("unknown"),e=e.object;const r=s.join("");return t||h.includes(r)?r:null}build(){return this.toString().length>0}astGeneric(e,t){if(null===e)throw this.astErrorOutput("NULL ast",e);if(Array.isArray(e)){for(let s=0;s0?r[r.length-1]:0;return new Error(`${e} on line ${r.length}, position ${i.length}:\n ${s}`)}astDebuggerStatement(e,t){return t}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);return t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t}astFunction(e,t){throw new Error(`"astFunction" not defined on ${this.constructor.name}`)}astFunctionDeclaration(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}astFunctionExpression(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}isChildFunction(e){for(let t=0;t1?t.push("(",r.join(","),")"):t.push(r[0]),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)||(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator))),t}checkAndUpconvertBitwiseUnary(e,t){}astUpdateExpression(e,t){return e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t}astLogicalExpression(e,t){return t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),t.push(")"),t}astMemberExpression(e,t){return t}astCallExpression(e,t){return t}astArrayExpression(e,t){return t}getMemberExpressionDetails(e){if("MemberExpression"!==e.type)throw this.astErrorOutput(`Expression ${e.type} not a MemberExpression`,e);let t=null,s=null;const r=this.getVariableSignature(e);switch(r){case"value":return null;case"value.thread.value":case"this.thread.value":case"this.output.value":return{signature:r,type:"Integer",name:e.property.name};case"value[]":if("string"!=typeof e.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object),xProperty:e.property};case"value[][]":if("string"!=typeof e.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object),yProperty:e.object.property,xProperty:e.property};case"value[][][]":if("string"!=typeof e.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value[][][][]":if("string"!=typeof e.object.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.object.name,{name:t,origin:"user",signature:r,type:this.getVariableType(e.object.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(this.isAstMathVariable(e))return t=e.property.name,{name:t,origin:"Math",type:"Number",signature:r};switch(e.property.name){case"r":case"g":case"b":case"a":return t=e.object.name,{name:t,property:e.property.name,origin:"user",signature:r,type:"Number"};default:throw this.astErrorOutput("Unexpected expression",e)}case"this.constants.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.property.name,s=this.getConstantType(t),!s)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:s,origin:"constants",signature:r};case"this.constants.value[]":if("string"!=typeof e.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.property.name,s=this.getConstantType(t),!s)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:s,origin:"constants",signature:r,xProperty:e.property};case"this.constants.value[][]":if("string"!=typeof e.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.property.name,s=this.getConstantType(t),!s)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:s,origin:"constants",signature:r,yProperty:e.object.property,xProperty:e.property};case"this.constants.value[][][]":if("string"!=typeof e.object.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.object.property.name,s=this.getConstantType(t),!s)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:s,origin:"constants",signature:r,zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"fn()[]":case"fn()[][]":case"[][]":return{signature:r,property:e.property};default:throw this.astErrorOutput("Unexpected expression",e)}}findIdentifierOrigin(e){const t=[this.ast];for(;t.length>0;){const s=t[0];if("VariableDeclarator"===s.type&&s.id&&s.id.name&&s.id.name===e.name)return s;if(t.shift(),s.argument)t.push(s.argument);else if(s.body)t.push(s.body);else if(s.declarations)t.push(s.declarations);else if(Array.isArray(s))for(let e=0;e0;){const e=t.pop();if("ReturnStatement"===e.type)return e;if("FunctionDeclaration"!==e.type)if(e.argument)t.push(e.argument);else if(e.body)t.push(e.body);else if(e.declarations)t.push(e.declarations);else if(Array.isArray(e))for(let s=0;s{const{FunctionNode:s}=l();t.exports={CPUFunctionNode:class extends s{markupUserName(e){return this.isRootKernel&&this.getAssignedArguments().has(e)?`cellShadow_user_${e}`:`user_${e}`}astFunction(e,t){if(!this.isRootKernel){t.push("function"),t.push(" "),t.push(this.name),t.push("(");for(let e=0;e0&&t.push(", "),t.push("user_"),t.push(s)}t.push(") {\n")}if(this.isRootKernel){for(const e of this.getAssignedArguments())t.push(`let cellShadow_user_${e} = user_${e};\n`);t.push("kernelBody: {\n")}for(let s=0;s0&&t.push(s.join(""),";\n"),t.push(`for (let ${e}=0;${e}0&&t.push(`if (!${r.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);return t.push("for (let i = 0; i < LOOP_MAX; i++) {"),t.push("if ("),this.astGeneric(e.test,t),t.push(") {\n"),this.astGeneric(e.body,t),t.push("} else {\n"),t.push("break;\n"),t.push("}\n"),t.push("}\n"),t}astDoWhileStatement(e,t){if("DoWhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const s=`safeI${this.astKey(e,"_")}`;return t.push(`let ${s} = 0;\n`),t.push("do {"),this.astGeneric(e.body,t),t.push("} while (("),this.astGeneric(e.test,t),t.push(`) && ++${s} < LOOP_MAX);\n`),t}astAssignmentExpression(e,t){const s=this.isState("assignment-as-statement");return s?this.popState("assignment-as-statement"):t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),s||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let s=0;s0&&t.push(",");const r=s[e],n=this.getDeclaration(r.id);n.valueType||(n.valueType=this.getType(r.init)),this.astGeneric(r,t)}return this.isState("in-for-loop-init")||t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchStatement(e,t){const{discriminant:s,cases:r}=e;t.push("switch ("),this.astGeneric(s,t),t.push(") {\n");for(let e=0;e0&&(this.astGeneric(r[e].consequent,t),t.push("break;\n"))):(t.push("default:\n"),this.astGeneric(r[e].consequent,t),r[e].consequent&&r[e].consequent.length>0&&t.push("break;\n"));t.push("\n}")}astThisExpression(e,t){return t.push("_this"),t}astMemberExpression(e,t){const{signature:s,type:r,property:n,xProperty:i,yProperty:a,zProperty:o,name:u,origin:l}=this.getMemberExpressionDetails(e);switch(s){case"this.thread.value":return t.push(`_this.thread.${u}`),t;case"this.output.value":switch(u){case"x":t.push("outputX");break;case"y":t.push("outputY");break;case"z":t.push("outputZ");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":default:throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value.value":if("Math"===l)return t.push(Math[u]),t;switch(n){case"r":return t.push(`user_${u}[0]`),t;case"g":return t.push(`user_${u}[1]`),t;case"b":return t.push(`user_${u}[2]`),t;case"a":return t.push(`user_${u}[3]`),t}break;case"this.constants.value":case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":break;case"fn()[]":return this.astGeneric(e.object,t),t.push("["),this.astGeneric(e.property,t),t.push("]"),t;case"fn()[][]":return this.astGeneric(e.object.object,t),t.push("["),this.astGeneric(e.object.property,t),t.push("]"),t.push("["),this.astGeneric(e.property,t),t.push("]"),t}if(!e.computed)switch(r){case"Number":case"Integer":case"Float":case"Boolean":return t.push("user"===l?this.markupUserName(u):`${l}_${u}`),t}const h="user"===l?this.markupUserName(u):`${l}_${u}`;{let e,s;if("constants"===l){const t=this.constants[u];s="Input"===this.constantTypes[u],e=s?t.size:null}else s=this.isInput(u),e=s?this.argumentSizes[this.argumentNames.indexOf(u)]:null;t.push(`${h}`),o&&a?s?(t.push("[("),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"(outputY * outputX)":e[1]*e[0]})+(`),this.astGeneric(a,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(i,t),t.push("]")):(t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]"),t.push("["),this.astGeneric(i,t),t.push("]")):a?s?(t.push("[("),this.astGeneric(a,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(i,t),t.push("]")):(t.push("["),this.astGeneric(a,t),t.push("]"),t.push("["),this.astGeneric(i,t),t.push("]")):void 0!==i&&(t.push("["),this.astGeneric(i,t),t.push("]"))}return t}astCallExpression(e,t){if("CallExpression"!==e.type)throw this.astErrorOutput("Unknown CallExpression",e);let s=this.astMemberExpressionUnroll(e.callee);this.calledFunctions.indexOf(s)<0&&this.calledFunctions.push(s),this.isAstMathFunction(e),this.onFunctionCall&&this.onFunctionCall(this.name,s,e.arguments),t.push(s),t.push("(");const r=this.lookupFunctionArgumentTypes(s)||[];for(let n=0;n0&&t.push(", "),this.astGeneric(i,t)}return t.push(")"),t}astArrayExpression(e,t){const s=this.getType(e),r=e.elements.length,n=[];for(let t=0;t{const{utils:s}=i();t.exports={cpuKernelString:function(e,t){const r=[],n=[],i=[],a=!/^function/.test(e.color.toString());if(r.push(" const { context, canvas, constants: incomingConstants } = settings;",` const output = new Int32Array(${JSON.stringify(Array.from(e.output))});`,` const _constantTypes = ${JSON.stringify(e.constantTypes)};`,` const _constants = ${function(e,t){const s=[];for(const r in t){if(!t.hasOwnProperty(r))continue;const n=t[r],i=e[r];switch(n){case"Number":case"Integer":case"Float":case"Boolean":s.push(`${r}:${i}`);break;case"Array(2)":case"Array(3)":case"Array(4)":case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":s.push(`${r}:new ${i.constructor.name}(${JSON.stringify(Array.from(i))})`)}}return`{ ${s.join()} }`}(e.constants,e.constantTypes)};`),n.push(" constants: _constants,"," context,"," output,"," thread: {x: 0, y: 0, z: 0},"),e.graphical){r.push(` const _imageData = context.createImageData(${e.output[0]}, ${e.output[1]});`),r.push(` const _colorData = new Uint8ClampedArray(${e.output[0]} * ${e.output[1]} * 4);`);const t=s.flattenFunctionToString((a?"function ":"")+e.color.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:(e,t)=>null}),o=s.flattenFunctionToString((a?"function ":"")+e.getPixels.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:()=>null});n.push(" _imageData,"," _colorData,",` color: ${t},`),i.push(` kernel.getPixels = ${o};`)}const o=[],u=Object.keys(e.constantTypes);for(let t=0;t"this"===t?(a?"function ":"")+e[s].toString():null,thisLookup:e=>{switch(e){case"canvas":return;case"context":return"context"}}});i.push(t),n.push(" _mediaTo2DArray,"),n.push(" _imageTo3DArray,")}else if(-1!==e.argumentTypes.indexOf("HTMLImage")||-1!==o.indexOf("HTMLImage")){const t=s.flattenFunctionToString((a?"function ":"")+e._mediaTo2DArray.toString(),{findDependency:(e,t)=>null,thisLookup:e=>{switch(e){case"canvas":return"settings.canvas";case"context":return"settings.context"}throw new Error("unhandled thisLookup")}});i.push(t),n.push(" _mediaTo2DArray,")}return`function(settings) {\n${r.join("\n")}\n for (const p in _constantTypes) {\n if (!_constantTypes.hasOwnProperty(p)) continue;\n const type = _constantTypes[p];\n switch (type) {\n case 'Number':\n case 'Integer':\n case 'Float':\n case 'Boolean':\n case 'Array(2)':\n case 'Array(3)':\n case 'Array(4)':\n case 'Matrix(2)':\n case 'Matrix(3)':\n case 'Matrix(4)':\n if (incomingConstants.hasOwnProperty(p)) {\n console.warn('constant ' + p + ' of type ' + type + ' cannot be resigned');\n }\n continue;\n }\n if (!incomingConstants.hasOwnProperty(p)) {\n throw new Error('constant ' + p + ' not found');\n }\n _constants[p] = incomingConstants[p];\n }\n const kernel = (function() {\n${e._kernelString}\n })\n .apply({ ${n.join("\n")} });\n ${i.join("\n")}\n return kernel;\n}`}}}),p=e((e,t)=>{const{Kernel:s}=a(),{FunctionBuilder:r}=o(),{CPUFunctionNode:n}=h(),{utils:u}=i(),{cpuKernelString:l}=c();t.exports={CPUKernel:class extends s{static getFeatures(){return this.features}static get features(){return Object.freeze({kernelMap:!0,isIntegerDivisionAccurate:!0})}static get isSupported(){return!0}static isContextMatch(e){return!1}static get mode(){return"cpu"}static nativeFunctionArguments(){return null}static nativeFunctionReturnType(){throw new Error(`Looking up native function return type not supported on ${this.name}`)}static combineKernels(e){return e}static getSignature(e,t){return"cpu"+(t.length>0?":"+t.join(","):"")}constructor(e,t){super(e,t),this.mergeSettings(e.settings||t),this._imageData=null,this._colorData=null,this._kernelString=null,this._prependedString=[],this.thread={x:0,y:0,z:0},this.translatedSources=null}initCanvas(){return"undefined"!=typeof document?document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(0,0):void 0}initContext(){return this.canvas?this.canvas.getContext("2d",{willReadFrequently:!0}):null}initPlugins(e){return[]}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=u.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=u.getDimensions(t);else{if("NumberTexture"!==t&&"ArrayTexture(4)"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=e[0].output}}if(this.graphical&&2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");this.checkOutput()}translateSource(){if(this.leadingReturnStatement=this.output.length>1?"resultX[x] = ":"result[x] = ",this.subKernels){const e=[];for(let t=0;t1?`resultX_${s}[x] = subKernelResult_${s};\n`:`result_${s}[x] = subKernelResult_${s};\n`)}this.followingReturnStatement=e.join("")}const e=r.fromKernel(this,n);this.translatedSources=e.getPrototypes("kernel"),this.graphical||this.returnType||(this.returnType=e.getKernelResultType())}build(){if(this.built)return;if(null!==this.randomSeed&&console.warn("randomSeed is not supported in cpu mode; Math.random() will be unseeded"),this.setupConstants(),this.setupArguments(arguments),this.validateSettings(arguments),this.translateSource(),this.graphical){const{canvas:e,output:t}=this;if(!e)throw new Error("no canvas available for using graphical output");const s=t[0],r=t[1]||1;e.width=s,e.height=r,this._imageData=this.context.createImageData(s,r),this._colorData=new Uint8ClampedArray(s*r*4)}const e=this.getKernelString();this.kernelString=e,this.debug&&(console.log("Function output:"),console.log(e));try{this.run=new Function([],e).bind(this)()}catch(e){console.error("An error occurred compiling the javascript: ",e)}this.buildSignature(arguments),this.built=!0}color(e,t,s,r){void 0===r&&(r=1),e=Math.floor(255*e),t=Math.floor(255*t),s=Math.floor(255*s),r=Math.floor(255*r);const n=this.output[0],i=this.output[1],a=this.thread.x+(i-this.thread.y-1)*n;this._colorData[4*a+0]=e,this._colorData[4*a+1]=t,this._colorData[4*a+2]=s,this._colorData[4*a+3]=r}getKernelString(){if(null!==this._kernelString)return this._kernelString;let e=null,{translatedSources:t}=this;return t.length>1?t=t.filter(t=>/^function/.test(t)?t:(e=t,!1)):e=t.shift(),this._kernelString=` const LOOP_MAX = ${this._getLoopMaxString()};\n ${this.injectedNative||""}\n const _this = this;\n ${this._resultKernelHeader()}\n ${this._processConstants()}\n return (${this.argumentNames.map(e=>"user_"+e).join(", ")}) => {\n ${this._prependedString.join("")}\n ${this._earlyThrows()}\n ${this._processArguments()}\n ${this.graphical?this._graphicalKernelBody(e):this._resultKernelBody(e)}\n ${t.length>0?t.join("\n"):""}\n };`}toString(){return l(this)}_getLoopMaxString(){return this.loopMaxIterations?` ${parseInt(this.loopMaxIterations)};`:" 1000;"}_processConstants(){if(!this.constants)return"";const e=[];for(let t in this.constants)switch(this.constantTypes[t]){case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":e.push(` const constants_${t} = this._mediaTo2DArray(this.constants.${t});\n`);break;case"HTMLImageArray":e.push(` const constants_${t} = this._imageTo3DArray(this.constants.${t});\n`);break;case"Input":e.push(` const constants_${t} = this.constants.${t}.value;\n`);break;default:e.push(` const constants_${t} = this.constants.${t};\n`)}return e.join("")}_earlyThrows(){if(this.graphical)return"";if(this.immutable)return"";if(!this.pipeline)return"";const e=[];for(let t=0;t`user_${r} === result_${e.name}`).join(" || ");t.push(`user_${r} === result${n?` || ${n}`:""}`)}return`if (${t.join(" || ")}) throw new Error('Source and destination arrays are the same. Use immutable = true');`}_processArguments(){const e=[];for(let t=0;t0?e.width:e.videoWidth,r=e.height>0?e.height:e.videoHeight;t.width=0;e--){const t=a[e]=new Array(s);for(let e=0;e`const result_${e.name} = new ${t}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_mutableKernel1DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const result = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const result_${t.name} = new ${e}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}`}_resultMutableKernel1DLoop(e){return` const outputX = _this.output[0];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_resultImmutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_mutableKernel2DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = result[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = result_${t.name}[y] = new ${e}(outputX);\n`).join("")}\n }`}_resultMutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y];\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_graphicalKernel2DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_resultImmutableKernel3DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = resultY_${e.name}[y] = new ${t}(outputX);\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_mutableKernel3DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = resultY[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = resultY_${t.name}[y] = new ${e}(outputX);\n`).join(" ")}\n }\n }`}_resultMutableKernel3DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z];\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_kernelOutput(){return this.subKernels?`\n return {\n result: result,\n ${this.subKernels.map(e=>`${e.property}: result_${e.name}`).join(",\n ")}\n };`:"\n return result;"}_mapSubKernels(e){return null===this.subKernels?[""]:this.subKernels.map(e)}destroy(e){e&&delete this.canvas}static destroyContext(e){}toJSON(){const e=super.toJSON();return e.functionNodes=r.fromKernel(this,n).toJSON(),e}setOutput(e){super.setOutput(e);const[t,s]=this.output;this.graphical&&(this._imageData=this.context.createImageData(t,s),this._colorData=new Uint8ClampedArray(t*s*4))}prependString(e){if(this._kernelString)throw new Error("Kernel already built");this._prependedString.push(e)}hasPrependString(e){return this._prependedString.indexOf(e)>-1}}}}),d=e((e,t)=>{t.exports={}}),f=e((e,t)=>{const{Texture:s}=n();function r(e,t){e.activeTexture(e.TEXTURE15),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST)}t.exports={GLTexture:class extends s{get textureType(){throw new Error(`"textureType" not implemented on ${this.name}`)}clone(){return new this.constructor(this)}beforeMutate(){return this.texture._refs>1&&(this.newTexture(),!0)}cloneTexture(){this.texture._refs--;const{context:e,size:t,texture:s,kernel:n}=this;n.debug&&console.warn("cloning internal texture"),e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),r(e,s),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,s,0);const i=e.createTexture();r(e,i),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t[0],t[1]),i._refs=1,this.texture=i}newTexture(){this.texture._refs--;const e=this.context,t=this.size;this.kernel.debug&&console.warn("new internal texture");const s=e.createTexture();r(e,s),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),s._refs=1,this.texture=s}clear(){if(this.texture._refs){this.texture._refs--;const e=this.context,t=this.texture=e.createTexture();r(e,t);const s=this.size;t._refs=1,e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,s[0],s[1],0,this.textureFormat,this.textureType,null)}const{context:e,texture:t}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.bindTexture(e.TEXTURE_2D,t),r(e,t),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}delete(){this._deleted||(this._deleted=!0,this.texture._refs&&(this.texture._refs--,this.texture._refs)||(this.kernel&&this.kernel.deleteTexture?this.kernel.deleteTexture(this.texture):this.context.deleteTexture(this.texture)))}framebuffer(){return this._framebuffer||(this._framebuffer=this.kernel.getRawValueFramebuffer(this.size[0],this.size[1])),this._framebuffer}}}}),m=e((e,t)=>{const{utils:s}=i(),{GLTexture:r}=f();t.exports={GLTextureFloat:class extends r{get textureType(){return this.context.FLOAT}constructor(e){super(e),this.type="ArrayTexture(1)"}renderRawOutput(){const e=this.context,t=this.size;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const s=new Float32Array(t[0]*t[1]*4);return e.readPixels(0,0,t[0],t[1],e.RGBA,e.FLOAT,s),s}renderValues(){return this._deleted?null:this.renderRawOutput()}toArray(){return s.erectFloat(this.renderValues(),this.output[0])}}}}),g=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return s.erectArray2(this.renderValues(),this.output[0],this.output[1])}}}}),y=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return s.erect2DArray2(this.renderValues(),this.output[0],this.output[1])}}}}),x=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray2Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return s.erect3DArray2(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),b=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return s.erectArray3(this.renderValues(),this.output[0])}}}}),v=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return s.erect2DArray3(this.renderValues(),this.output[0],this.output[1])}}}}),S=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray3Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return s.erect3DArray3(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),T=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return s.erectArray4(this.renderValues(),this.output[0])}}}}),A=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return s.erect2DArray4(this.renderValues(),this.output[0],this.output[1])}}}}),w=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureArray4Float3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return s.erect3DArray4(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),_=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureFloat2D:class extends r{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return s.erect2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),E=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureFloat3D:class extends r{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return s.erect3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),I=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return s.erectMemoryOptimizedFloat(this.renderValues(),this.output[0])}}}}),k=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized2D:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return s.erectMemoryOptimized2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),C=e((e,t)=>{const{utils:s}=i(),{GLTextureFloat:r}=m();t.exports={GLTextureMemoryOptimized3D:class extends r{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return s.erectMemoryOptimized3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),L=e((e,t)=>{const{utils:s}=i(),{GLTexture:r}=f();t.exports={GLTextureUnsigned:class extends r{get textureType(){return this.context.UNSIGNED_BYTE}constructor(e){super(e),this.type="NumberTexture"}renderRawOutput(){const{context:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const t=new Uint8Array(this.size[0]*this.size[1]*4);return e.readPixels(0,0,this.size[0],this.size[1],e.RGBA,e.UNSIGNED_BYTE,t),t}renderValues(){return this._deleted?null:new Float32Array(this.renderRawOutput().buffer)}toArray(){return s.erectPackedFloat(this.renderValues(),this.output[0])}}}}),D=e((e,t)=>{const{utils:s}=i(),{GLTextureUnsigned:r}=L();t.exports={GLTextureUnsigned2D:class extends r{constructor(e){super(e),this.type="NumberTexture"}toArray(){return s.erect2DPackedFloat(this.renderValues(),this.output[0],this.output[1])}}}}),F=e((e,t)=>{const{utils:s}=i(),{GLTextureUnsigned:r}=L();t.exports={GLTextureUnsigned3D:class extends r{constructor(e){super(e),this.type="NumberTexture"}toArray(){return s.erect3DPackedFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),$=e((e,t)=>{const{GLTextureUnsigned:s}=L();t.exports={GLTextureGraphical:class extends s{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return this.renderValues()}}}}),R=e((e,t)=>{const{Kernel:s}=a(),{utils:r}=i(),{GLTextureArray2Float:n}=g(),{GLTextureArray2Float2D:o}=y(),{GLTextureArray2Float3D:u}=x(),{GLTextureArray3Float:l}=b(),{GLTextureArray3Float2D:h}=v(),{GLTextureArray3Float3D:c}=S(),{GLTextureArray4Float:p}=T(),{GLTextureArray4Float2D:d}=A(),{GLTextureArray4Float3D:f}=w(),{GLTextureFloat:R}=m(),{GLTextureFloat2D:N}=_(),{GLTextureFloat3D:M}=E(),{GLTextureMemoryOptimized:G}=I(),{GLTextureMemoryOptimized2D:O}=k(),{GLTextureMemoryOptimized3D:V}=C(),{GLTextureUnsigned:P}=L(),{GLTextureUnsigned2D:B}=D(),{GLTextureUnsigned3D:z}=F(),{GLTextureGraphical:U}=$();const K={int:"Integer",float:"Number",vec2:"Array(2)",vec3:"Array(3)",vec4:"Array(4)"};t.exports={GLKernel:class extends s{static get mode(){return"gpu"}static getIsFloatRead(){const e=new this("function kernelFunction() {\n return 1;\n }",{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[1],precision:"single",returnType:"Number",tactic:"speed"});e.build(),e.run();const t=e.renderOutput();return e.destroy(!0),1===t[0]}static getIsIntegerDivisionAccurate(){const e=new this(function(e,t){return e[this.thread.x]/t[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[2],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[6,6030401],[3,3991]];e.build.apply(e,t),e.run.apply(e,t);const s=e.renderOutput();return e.destroy(!0),2===s[0]&&1511===s[1]}static getIsSpeedTacticSupported(){const e=new this(function(e){return e[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[4],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[0,1,2,3]];e.build.apply(e,t),e.run.apply(e,t);const s=e.renderOutput();return e.destroy(!0),0===Math.round(s[0])&&1===Math.round(s[1])&&2===Math.round(s[2])&&3===Math.round(s[3])}static get testCanvas(){throw new Error(`"testCanvas" not defined on ${this.name}`)}static get testContext(){throw new Error(`"testContext" not defined on ${this.name}`)}static getFeatures(){const e=this.testContext,t=this.getIsDrawBuffers();return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),isTextureFloat:this.getIsTextureFloat(),isDrawBuffers:t,kernelMap:t,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static setupFeatureChecks(){throw new Error(`"setupFeatureChecks" not defined on ${this.name}`)}static getSignature(e,t){return e.getVariablePrecisionString()+(t.length>0?":"+t.join(","):"")}setFixIntegerDivisionAccuracy(e){return this.fixIntegerDivisionAccuracy=e,this}setPrecision(e){return this.precision=e,this}setFloatTextures(e){return r.warnDeprecated("method","setFloatTextures","setOptimizeFloatMemory"),this.floatTextures=e,this}static nativeFunctionArguments(e){const t=[],s=[],r=[],n=/^[a-zA-Z_]/,i=/[a-zA-Z_0-9]/;let a=0,o=null,u=null;for(;a0?r[r.length-1]:null;if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"*"!==h)if("MULTI_LINE_COMMENT"!==c||"*"!==l||"/"!==h)if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"/"!==h)if("COMMENT"!==c||"\n"!==l)if(null!==c||"("!==l){if("FUNCTION_ARGUMENTS"===c){if(")"===l){r.pop();break}if("f"===l&&"l"===h&&"o"===e[a+2]&&"a"===e[a+3]&&"t"===e[a+4]&&" "===e[a+5]){r.push("DECLARE_VARIABLE"),u="float",o="",a+=6;continue}if("i"===l&&"n"===h&&"t"===e[a+2]&&" "===e[a+3]){r.push("DECLARE_VARIABLE"),u="int",o="",a+=4;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"2"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec2",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"3"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec3",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"4"===e[a+3]&&" "===e[a+4]){r.push("DECLARE_VARIABLE"),u="vec4",o="",a+=5;continue}}else if("DECLARE_VARIABLE"===c){if(""===o){if(" "===l){a++;continue}if(!n.test(l))throw new Error("variable name is not expected string")}o+=l,i.test(h)||(r.pop(),s.push(o),t.push(K[u]))}a++}else r.push("FUNCTION_ARGUMENTS"),a++;else r.pop(),a++;else r.push("COMMENT"),a+=2;else r.pop(),a+=2;else r.push("MULTI_LINE_COMMENT"),a+=2}if(r.length>0)throw new Error("GLSL function was not parsable");return{argumentNames:s,argumentTypes:t}}static nativeFunctionReturnType(e){return K[e.match(/int|float|vec[2-4]/)[0]]}static combineKernels(e,t){e.apply(null,arguments);const{texSize:s,context:n,threadDim:i}=t.texSize;let a;if("single"===t.precision){const e=s[0],t=Math.ceil(s[1]/4);a=new Float32Array(e*t*4*4),n.readPixels(0,0,e,4*t,n.RGBA,n.FLOAT,a)}else{const e=new Uint8Array(s[0]*s[1]*4);n.readPixels(0,0,s[0],s[1],n.RGBA,n.UNSIGNED_BYTE,e),a=new Float32Array(e.buffer)}return a=a.subarray(0,i[0]*i[1]*i[2]),1===t.output.length?a:2===t.output.length?r.splitArray(a,t.output[0]):3===t.output.length?r.splitArray(a,t.output[0]*t.output[1]).map(function(e){return r.splitArray(e,t.output[0])}):void 0}constructor(e,t){super(e,t),this.transferValues=null,this.formatValues=null,this.TextureConstructor=null,this.renderOutput=null,this.renderRawOutput=null,this.texSize=null,this.translatedSource=null,this.compiledFragmentShader=null,this.compiledVertexShader=null,this.switchingKernels=null,this._textureSwitched=null,this._mappedTextureSwitched=null}checkTextureSize(){const{features:e}=this.constructor;if(this.texSize[0]>e.maxTextureSize||this.texSize[1]>e.maxTextureSize)throw new Error(`Texture size [${this.texSize[0]},${this.texSize[1]}] generated by kernel is larger than supported size [${e.maxTextureSize},${e.maxTextureSize}]`)}translateSource(){throw new Error(`"translateSource" not defined on ${this.constructor.name}`)}pickRenderStrategy(e){if(this.graphical)return this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=e=>e,this.TextureConstructor=U,null;if("unsigned"===this.precision)if(this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=this.readPackedPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=z,null):this.output[1]>0?(this.TextureConstructor=B,null):(this.TextureConstructor=P,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else switch(null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.renderOutput=this.renderValues,this.output[2]>0?(this.TextureConstructor=z,this.formatValues=r.erect3DPackedFloat,null):this.output[1]>0?(this.TextureConstructor=B,this.formatValues=r.erect2DPackedFloat,null):(this.TextureConstructor=P,this.formatValues=r.erectPackedFloat,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else{if("single"!==this.precision)throw new Error(`unhandled precision of "${this.precision}"`);if(this.renderRawOutput=this.readFloatPixelsToFloat32Array,this.transferValues=this.readFloatPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.optimizeFloatMemory?this.output[2]>0?(this.TextureConstructor=V,null):this.output[1]>0?(this.TextureConstructor=O,null):(this.TextureConstructor=G,null):this.output[2]>0?(this.TextureConstructor=M,null):this.output[1]>0?(this.TextureConstructor=N,null):(this.TextureConstructor=R,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,null):this.output[1]>0?(this.TextureConstructor=o,null):(this.TextureConstructor=n,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,null):this.output[1]>0?(this.TextureConstructor=h,null):(this.TextureConstructor=l,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,null):this.output[1]>0?(this.TextureConstructor=d,null):(this.TextureConstructor=p,null)}if(this.renderOutput=this.renderValues,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.optimizeFloatMemory)switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=V,this.formatValues=r.erectMemoryOptimized3DFloat,null):this.output[1]>0?(this.TextureConstructor=O,this.formatValues=r.erectMemoryOptimized2DFloat,null):(this.TextureConstructor=G,this.formatValues=r.erectMemoryOptimizedFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=r.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=r.erect2DArray2,null):(this.TextureConstructor=n,this.formatValues=r.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=r.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=r.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=r.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=r.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=r.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=r.erectArray4,null)}else switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=M,this.formatValues=r.erect3DFloat,null):this.output[1]>0?(this.TextureConstructor=N,this.formatValues=r.erect2DFloat,null):(this.TextureConstructor=R,this.formatValues=r.erectFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=r.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=r.erect2DArray2,null):(this.TextureConstructor=n,this.formatValues=r.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=r.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=r.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=r.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=r.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=r.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=r.erectArray4,null)}}throw new Error(`unhandled return type "${this.returnType}"`)}getKernelString(){throw new Error("abstract method call")}getMainResultTexture(){switch(this.returnType){case"LiteralInteger":case"Float":case"Integer":case"Number":return this.getMainResultNumberTexture();case"Array(2)":return this.getMainResultArray2Texture();case"Array(3)":return this.getMainResultArray3Texture();case"Array(4)":return this.getMainResultArray4Texture();default:throw new Error(`unhandled returnType type ${this.returnType}`)}}getMainResultKernelNumberTexture(){throw new Error("abstract method call")}getMainResultSubKernelNumberTexture(){throw new Error("abstract method call")}getMainResultKernelArray2Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray2Texture(){throw new Error("abstract method call")}getMainResultKernelArray3Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray3Texture(){throw new Error("abstract method call")}getMainResultKernelArray4Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray4Texture(){throw new Error("abstract method call")}getMainResultGraphical(){throw new Error("abstract method call")}getMainResultMemoryOptimizedFloats(){throw new Error("abstract method call")}getMainResultPackedPixels(){throw new Error("abstract method call")}getMainResultString(){return this.graphical?this.getMainResultGraphical():"single"===this.precision?this.optimizeFloatMemory?this.getMainResultMemoryOptimizedFloats():this.getMainResultTexture():this.getMainResultPackedPixels()}getMainResultNumberTexture(){return r.linesToString(this.getMainResultKernelNumberTexture())+r.linesToString(this.getMainResultSubKernelNumberTexture())}getMainResultArray2Texture(){return r.linesToString(this.getMainResultKernelArray2Texture())+r.linesToString(this.getMainResultSubKernelArray2Texture())}getMainResultArray3Texture(){return r.linesToString(this.getMainResultKernelArray3Texture())+r.linesToString(this.getMainResultSubKernelArray3Texture())}getMainResultArray4Texture(){return r.linesToString(this.getMainResultKernelArray4Texture())+r.linesToString(this.getMainResultSubKernelArray4Texture())}getFloatTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} float;\n`}getIntTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic,!0)} int;\n`}getSampler2DTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2D;\n`}getSampler2DArrayTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2DArray;\n`}renderTexture(){return this.immutable?this.texture.clone():this.texture}readPackedPixelsToUint8Array(){if("unsigned"!==this.precision)throw new Error('Requires this.precision to be "unsigned"');const{texSize:e,context:t}=this,s=new Uint8Array(e[0]*e[1]*4);return t.readPixels(0,0,e[0],e[1],t.RGBA,t.UNSIGNED_BYTE,s),s}readPackedPixelsToFloat32Array(){return new Float32Array(this.readPackedPixelsToUint8Array().buffer)}readFloatPixelsToFloat32Array(){if("single"!==this.precision)throw new Error('Requires this.precision to be "single"');const{texSize:e,context:t}=this,s=e[0],r=e[1],n=new Float32Array(s*r*4);return t.readPixels(0,0,s,r,t.RGBA,t.FLOAT,n),n}getPixels(e){const{context:t,output:s}=this,[n,i]=s,a=new Uint8Array(n*i*4);t.readPixels(0,0,n,i,t.RGBA,t.UNSIGNED_BYTE,a);const o=new Uint8ClampedArray((e?a:r.flipPixels(a,n,i)).buffer);return this.asyncMode?Promise.resolve(o):o}renderKernelsToArrays(){const e={result:this.renderOutput()};for(let t=0;t0){for(let e=0;e0){const{mappedTextures:s}=this;for(let r=0;r{const{utils:s}=i(),{FunctionNode:r}=l(),n={"<":"ceil",">=":"ceil",">":"floor","<=":"floor"};function a(e){if(!e||"object"!=typeof e)return!0;if(Array.isArray(e))return e.every(a);if("UpdateExpression"===e.type||"AssignmentExpression"===e.type||"SequenceExpression"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&!a(e[t]))return!1;return!0}function o(e){let t=!1;function s(e){if(!e||"object"!=typeof e||t)return!1;if(Array.isArray(e))return e.some(s);if("MemberExpression"===e.type&&e.computed)return!0;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&s(e[t]))return!0;return!1}return function e(r){if(r&&"object"==typeof r&&!t)if(Array.isArray(r))r.forEach(e);else if("MemberExpression"===r.type&&r.computed&&s(r.property))t=!0;else for(const t in r)"loc"!==t&&"range"!==t&&"parent"!==t&&e(r[t])}(e),t}function u(e,t){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>u(e,t));if("CallExpression"===e.type&&"Identifier"===e.callee.type&&e.callee.name===t)return!0;for(const s in e)if("loc"!==s&&"range"!==s&&"parent"!==s&&u(e[s],t))return!0;return!1}function h(e){let t=!1;return function e(s){if(s&&"object"==typeof s&&!t)if(Array.isArray(s))s.forEach(e);else if("CallExpression"===s.type&&"Identifier"===s.callee.type&&s.arguments.some(e=>u(e,s.callee.name)))t=!0;else for(const t in s)"loc"!==t&&"range"!==t&&"parent"!==t&&e(s[t])}(e),t}function c(e){const t="ExpressionStatement"===e.type&&"AssignmentExpression"===e.expression.type?e.expression:null;return function e(s){if(!s||"object"!=typeof s)return!0;if(Array.isArray(s))return s.every(e);if("string"==typeof s.type){if("UpdateExpression"===s.type||"SequenceExpression"===s.type)return!1;if("AssignmentExpression"===s.type&&s!==t)return!1}for(const t in s)if("loc"!==t&&"range"!==t&&"parent"!==t&&!e(s[t]))return!1;return!0}(e)}const p={"Matrix(2)":2,"Matrix(3)":3,"Matrix(4)":4},d={Array:"sampler2D","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4","Matrix(2)":"mat2","Matrix(3)":"mat3","Matrix(4)":"mat4",Array2D:"sampler2D",Array3D:"sampler2D",Boolean:"bool",Float:"float",Input:"sampler2D",Integer:"int",Number:"float",LiteralInteger:"float",NumberTexture:"sampler2D",MemoryOptimizedNumberTexture:"sampler2D","ArrayTexture(1)":"sampler2D","ArrayTexture(2)":"sampler2D","ArrayTexture(3)":"sampler2D","ArrayTexture(4)":"sampler2D",HTMLVideo:"sampler2D",HTMLCanvas:"sampler2D",OffscreenCanvas:"sampler2D",HTMLImage:"sampler2D",ImageBitmap:"sampler2D",ImageData:"sampler2D",HTMLImageArray:"sampler2DArray"},f={"===":"==","!==":"!="};t.exports={WebGLFunctionNode:class extends r{constructor(e,t){super(e,t),t&&t.hasOwnProperty("fixIntegerDivisionAccuracy")&&(this.fixIntegerDivisionAccuracy=t.fixIntegerDivisionAccuracy)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const s=this.getType(e.consequent),r=this.getType(e.alternate);return null===s&&null===r?(t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t):(t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t)}astFunction(e,t){if(this.isRootKernel)t.push("void");else{this.returnType||this.findLastReturn()&&(this.returnType=this.getType(e.body),"LiteralInteger"===this.returnType&&(this.returnType="Number"));const{returnType:s}=this;if(s){const e=d[s];if(!e)throw new Error(`unknown type ${s}`);t.push(e)}else t.push("void")}if(t.push(" "),t.push(this.name),t.push("("),!this.isRootKernel)for(let r=0;r0&&t.push(", ");let i=this.argumentTypes[this.argumentNames.indexOf(n)];if(!i)throw this.astErrorOutput(`Unknown argument ${n} type`,e);"LiteralInteger"===i&&(this.argumentTypes[r]=i="Number");const a=d[i];if(!a)throw this.astErrorOutput("Unexpected expression",e);const o=s.sanitizeName(n);"sampler2D"===a||"sampler2DArray"===a?t.push(`${a} user_${o},ivec2 user_${o}Size,ivec3 user_${o}Dim`):t.push(`${a} user_${o}`)}if(t.push(") {\n"),this.isRootKernel){const e=this.getAssignedArguments();for(let r=0;r>":"bitwiseSignedRightShift",">>>":"bitwiseZeroFillRightShift"}[e.operator];if(!s)return null;switch(t.push(s),t.push("("),this.getType(e.left)){case"Number":case"Float":this.castValueToInteger(e.left,t);break;case"LiteralInteger":this.castLiteralToInteger(e.left,t);break;default:this.astGeneric(e.left,t)}switch(t.push(","),this.getType(e.right)){case"Number":case"Float":this.castValueToInteger(e.right,t);break;case"LiteralInteger":this.castLiteralToInteger(e.right,t);break;default:this.astGeneric(e.right,t)}return t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){const s={"~":"bitwiseNot"}[e.operator];if(!s)return null;switch(t.push(s),t.push("("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("int("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("float("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),n=s.sanitizeName(e.name);if("Infinity"===e.name)t.push("3.402823466e+38");else if("Boolean"===r)if(this.argumentNames.indexOf(n)>-1){const s=this.markupUserName(e.name);t.push(s.startsWith("cellShadow_")?s:`bool(${s})`)}else t.push(`user_${n}`);else t.push(this.markupUserName(e.name));return t}markupUserName(e){const t=s.sanitizeName(e);if(this.isRootKernel&&this.getAssignedArguments().has(e)){const s=this.argumentNames.indexOf(e),r=-1===s?null:d[this.argumentTypes[s]];if("float"===r||"int"===r||"bool"===r)return`cellShadow_user_${t}`}return`user_${t}`}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const s=[],r=[],n=[],i=[];let a=null;if(e.init)if("VariableDeclaration"!==e.init.type)a=!1,this.astGeneric(e.init,s),s.push(";");else{const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,s);for(let e=0;e{const t=this.getDeclaration(e);return null!==t&&s.has(t)},a=e=>{if(e&&"object"==typeof e&&!n)if(Array.isArray(e))for(const t of e)a(t);else if("ForStatement"!==e.type||!e.init||"VariableDeclaration"!==e.init.type||!e.init.declarations.some(e=>e.id&&"Identifier"===e.id.type&&r.has(e.id.name)))if("AssignmentExpression"===e.type&&"Identifier"===e.left.type&&i(e.left))n=!0;else if("UpdateExpression"===e.type&&"Identifier"===e.argument.type&&i(e.argument))n=!0;else for(const t in e){if("loc"===t||"range"===t||"parent"===t)continue;const s=e[t];s&&"object"==typeof s&&a(s)}};return a(e.body),!n&&e.test&&a(e.test),n}emitForParts(e,t){const{initArr:s,testArr:r,updateArr:n,bodyArr:i,isSafe:a}=e;if(a){const e=s.join(""),a=";"!==e[e.length-1];t.push(`for (${e}${a?";":""}${r.join("")};${n.join("")}){\n`),t.push(i.join("")),t.push("}\n")}else{const e=this.getInternalVariableName("safeI");s.length>0&&t.push(s.join(""),"\n"),t.push(`for (int ${e}=0;${e}0&&t.push(`if (!${r.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const s=this.getInternalVariableName("safeI");return t.push(`for (int ${s}=0;${s}0){if (!`),this.astGeneric(e.test,t),t.push(") break;}\n"),this.astGeneric(e.body,t),t.push("}\n"),t}astAssignmentExpression(e,t){const s=this.isState("assignment-as-statement");if(s?this.popState("assignment-as-statement"):t.push("("),"%="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("mod("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else if("**="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("pow("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else{const s=this.getType(e.left),r=this.getType(e.right);this.astGeneric(e.left,t),t.push(e.operator),"Integer"!==s&&"Integer"===r?(t.push("float("),this.astGeneric(e.right,t),t.push(")")):"Integer"===s&&"LiteralInteger"===r?this.castLiteralToInteger(e.right,t):this.astGeneric(e.right,t)}return s||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let s=0;snull!==e&&(o(e)||h(e))))return null;const i=e=>JSON.parse(JSON.stringify(e)),a=e=>({type:"IfStatement",test:{type:"UnaryExpression",operator:"!",prefix:!0,argument:e},consequent:{type:"BlockStatement",body:[{type:"BreakStatement",label:null}]},alternate:null}),u=e=>"VariableDeclaration"===e.type?e:{type:"ExpressionStatement",expression:e},l="BlockStatement"===e.body.type?e.body.body.slice():[e.body],c=(e,t)=>{const s=e=>{if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(s);switch(e.type){case"ContinueStatement":return{type:"BlockStatement",body:[...t(),e]};case"ForStatement":case"WhileStatement":case"DoWhileStatement":default:return e;case"IfStatement":return{...e,consequent:s(e.consequent),alternate:s(e.alternate)};case"BlockStatement":return{...e,body:e.body.map(s)};case"SwitchStatement":return{...e,cases:e.cases.map(e=>({...e,consequent:e.consequent.map(s)}))}}};return e.map(s)},p=[];"DoWhileStatement"===t?(p.push(...r?c(l,()=>[a(i(r))]):l),r&&p.push(a(r))):(r&&p.push(a(r)),p.push(...n?c(l,()=>[u(i(n))]):l),n&&p.push(u(n)));const d={type:"BlockStatement",body:[...s?[u(s)]:[],{type:"WhileStatement",test:{type:"Literal",value:!0,raw:"true"},body:{type:"BlockStatement",body:p}}]};return this.stampSyntheticNodes(d),d}stampSyntheticNodes(e){let t=this.syntheticNodeId||1073741824;const s=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(s);else{"string"==typeof e.type&&void 0===e.start&&(e.start=t,e.end=t+1,t+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&s(e[t])}};s(e),this.syntheticNodeId=t}linearizeStatement(e){const t=[];let s=!1,r=this.linearTempId||0;const n=e=>({type:"Identifier",name:e}),i=(e,t,s)=>({type:"VariableDeclaration",kind:e,declarations:[{type:"VariableDeclarator",id:n(t),init:s}]}),o=(e,t)=>{const s="hoistSeq"+r++;return e.push(i("const",s,t)),n(s)},l=e=>!a(e),h=(e,t)=>{if(s||!e||"object"!=typeof e)return e;switch(e.type){case"Identifier":case"Literal":case"ThisExpression":return e;case"MemberExpression":{const s=h(e.object,t),r=e.computed?h(e.property,t):e.property;return{...e,object:s,property:r}}case"CallExpression":{const s=e.arguments.map(e=>h(e,t));if("Identifier"===e.callee.type)for(let r=0;rh(e,t))};case"UpdateExpression":{if("Identifier"!==e.argument.type)return s=!0,e;if(e.prefix)return t.push({type:"ExpressionStatement",expression:e}),o(t,e.argument);const r=o(t,e.argument);return t.push({type:"ExpressionStatement",expression:e}),r}case"AssignmentExpression":{if("Identifier"!==e.left.type)return s=!0,e;const r=h(e.right,t);return t.push({type:"ExpressionStatement",expression:{...e,right:r}}),o(t,e.left)}case"SequenceExpression":for(let s=0;s({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:n(e),right:t}});return o.push(d(a,c)),u.push(d(a,p)),t.push({type:"IfStatement",test:s,consequent:{type:"BlockStatement",body:o},alternate:{type:"BlockStatement",body:u}}),n(a)}case"LogicalExpression":{if(!l(e.right))return{...e,left:h(e.left,t)};const s=h(e.left,t),a="hoistSeq"+r++;t.push(i("let",a,s));const o=[],u=h(e.right,o);return o.push({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:n(a),right:u}}),t.push({type:"IfStatement",test:"&&"===e.operator?n(a):{type:"UnaryExpression",operator:"!",prefix:!0,argument:n(a)},consequent:{type:"BlockStatement",body:o},alternate:null}),n(a)}default:return s=!0,e}};switch(e.type){case"ExpressionStatement":{const s=e.expression;if("AssignmentExpression"===s.type&&"Identifier"===s.left.type){const e=h(s.right,t);t.push({type:"ExpressionStatement",expression:{...s,right:e}})}else{const e=h(s,t);"UpdateExpression"!==e.type&&"AssignmentExpression"!==e.type||t.push({type:"ExpressionStatement",expression:e})}break}case"VariableDeclaration":for(let s=0;s{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(p);else{"string"==typeof e.type&&void 0===e.start&&(e.start=c,e.end=c+1,c+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&p(e[t])}};return p(t),this.syntheticNodeId=c,t}astStatementWithHoisting(e,t){switch(e.type){case"ExpressionStatement":case"VariableDeclaration":case"ReturnStatement":{if(!c(e))return this.astGeneric(e,t);const s=this.hoistedIndexReads,r=this.hoistedIndexReads=[],n=[];return this.astGeneric(e,n),this.hoistedIndexReads=s,t.push(...r,...n),t}default:return this.astGeneric(e,t)}}astVariableDeclaration(e,t){const r=e.declarations;if(!r||!r[0]||!r[0].init)throw this.astErrorOutput("Unexpected expression",e);const n=[];let i=null;const a=[];let o=[];for(let t=0;t0&&a.push(o.join(",")),n.push(a.join(";")),t.push(n.join("")),t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchCaseConsequent(e,t){const s=[];for(let t=0;t{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const s in e)if("loc"!==s&&"range"!==s&&"parent"!==s&&t(e[s]))return!0;return!1};if(t(s[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",s[e])}for(let e=0;es+1){u=!0,this.astSwitchCaseConsequent(r[s].consequent,o);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(r[s].consequent,t),t.push("\n}")}return u&&(t.push(" else {"),t.push(o.join("")),t.push("}")),t}astThisExpression(e,t){return t.push("this"),t}astMemberExpression(e,t){const{property:r,name:n,signature:i,origin:a,type:o,xProperty:u,yProperty:l,zProperty:h}=this.getMemberExpressionDetails(e);switch(i){case"value.thread.value":case"this.thread.value":if("x"!==n&&"y"!==n&&"z"!==n)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`threadId.${n}`),t;case"this.output.value":if(this.dynamicOutput)switch(n){case"x":this.isState("casting-to-float")?t.push("float(uOutputDim.x)"):t.push("uOutputDim.x");break;case"y":this.isState("casting-to-float")?t.push("float(uOutputDim.y)"):t.push("uOutputDim.y");break;case"z":this.isState("casting-to-float")?t.push("float(uOutputDim.z)"):t.push("uOutputDim.z");break;default:throw this.astErrorOutput("Unexpected expression",e)}else switch(n){case"x":this.isState("casting-to-integer")?t.push(this.output[0]):t.push(this.output[0],".0");break;case"y":this.isState("casting-to-integer")?t.push(this.output[1]):t.push(this.output[1],".0");break;case"z":this.isState("casting-to-integer")?t.push(this.output[2]):t.push(this.output[2],".0");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===a)return t.push(Math[n]),t;const i=s.sanitizeName(n);switch(r){case"r":return t.push(`user_${i}.r`),t;case"g":return t.push(`user_${i}.g`),t;case"b":return t.push(`user_${i}.b`),t;case"a":return t.push(`user_${i}.a`),t}break;case"this.constants.value":if(void 0===u)switch(o){case"Array(2)":case"Array(3)":case"Array(4)":return t.push(`constants_${s.sanitizeName(n)}`),t}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":break;case"fn()[]":return this.astCallExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t;case"fn()[][]":{const s=e.object.property,r=e.property,n=p[this.getType(e.object.object)],i=e=>"LiteralInteger"===this.getType(e);return!n||i(s)&&i(r)?(this.astCallExpression(e.object.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(s)),t.push("]"),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t):(t.push(`getMatrix${n}(`),this.astCallExpression(e.object.object,t),t.push(", "),t.push(this.memberExpressionPropertyMarkup(s)),t.push(", "),t.push(this.memberExpressionPropertyMarkup(r)),t.push(")"),t)}case"[][]":return this.astArrayExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t;default:throw this.astErrorOutput("Unexpected expression",e)}if(!1===e.computed)switch(o){case"Number":case"Integer":case"Float":case"Boolean":return t.push(`${a}_${s.sanitizeName(n)}`),t}const c=`${a}_${s.sanitizeName(n)}`;switch(o){case"Array(2)":case"Array(3)":case"Array(4)":this.astGeneric(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(u)),t.push("]");break;case"HTMLImageArray":t.push(`getImage3D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(1)":t.push(`getFloatFromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(2)":case"Array2D(2)":case"Array3D(2)":t.push(`getMemoryOptimizedVec2(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(2)":t.push(`getVec2FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(3)":case"Array2D(3)":case"Array3D(3)":t.push(`getMemoryOptimizedVec3(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(3)":t.push(`getVec3FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(4)":case"Array2D(4)":case"Array3D(4)":t.push(`getMemoryOptimizedVec4(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(4)":case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":t.push(`getVec4FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"NumberTexture":case"Array":case"Array2D":case"Array3D":case"Array4D":case"Input":case"Number":case"Float":case"Integer":if("single"===this.precision)t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");else{const e="user"===a?this.lookupFunctionArgumentBitRatio(this.name,n):this.constantBitRatios[n];switch(e){case 1:t.push(`get8(${c}, ${c}Size, ${c}Dim, `);break;case 2:t.push(`get16(${c}, ${c}Size, ${c}Dim, `);break;case 4:case 0:t.push(`get32(${c}, ${c}Size, ${c}Dim, `);break;default:throw new Error(`unhandled bit ratio of ${e}`)}this.memberExpressionXYZ(u,l,h,t),t.push(")")}break;case"MemoryOptimizedNumberTexture":t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`${c}[${this.memberExpressionPropertyMarkup(l)}]`),l&&t.push(`[${this.memberExpressionPropertyMarkup(u)}]`);break;default:throw new Error(`unhandled member expression "${o}"`)}return t}astCallExpression(e,t){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);let r=null;const n=this.isAstMathFunction(e);if(r=n||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!r)throw this.astErrorOutput("Unhandled function, couldn't find name",e);switch(r){case"pow":r="_pow";break;case"round":r="_round"}if(this.calledFunctions.indexOf(r)<0&&this.calledFunctions.push(r),"random"===r&&this.plugins&&this.plugins.length>0)for(let e=0;e0&&t.push(", "),"Integer"===n)this.castValueToFloat(r,t);else this.astGeneric(r,t)}else{const n=this.lookupFunctionArgumentTypes(r)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(r,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("int("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("float("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.astGeneric(a,t);continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){if("Identifier"===a.type)t.push(`user_${s.sanitizeName(a.name)}`);else{if("ArrayExpression"!==a.type&&"MemberExpression"!==a.type&&"CallExpression"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.astGeneric(a,t)}continue}break;case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLImageArray":case"HTMLVideo":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":case"Array":case"Input":if(o===u){if("Identifier"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.triggerImplyArgumentBitRatio(this.name,a.name,r,i);const n=s.sanitizeName(a.name);t.push(`user_${n},user_${n}Size,user_${n}Dim`);continue}}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),t}astArrayExpression(e,t){const s=this.getType(e),r=e.elements.length;switch(s){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`mat${r}(`);break;default:t.push(`vec${r}(`)}for(let s=0;s0&&t.push(", ");const r=e.elements[s];this.astGeneric(r,t)}return t.push(")"),t}memberExpressionXYZ(e,t,s,r){return s?r.push(this.memberExpressionPropertyMarkup(s),", "):r.push("0, "),t?r.push(this.memberExpressionPropertyMarkup(t),", "):r.push("0, "),r.push(this.memberExpressionPropertyMarkup(e)),r}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.astGeneric(e,t)}const r=t.join("");if(this.hoistedIndexReads&&/\b\w+\((user_|constants_)\w+, \1\w+Size/.test(r)){const e=`hoisted_${this.hoistedIndexReads.length}_${s.sanitizeName(this.name)}`,t=r.startsWith("int(");return this.hoistedIndexReads.push(`${t?"int":"float"} ${e}=${r};\n`),e}return r}}}}),M=e((e,t)=>{t.exports={name:"math-random-uniformly-distributed",onBeforeRun:e=>{if(null===e.randomSeed||void 0===e.randomSeed)return e.setUniform1f("randomSeed1",Math.random()),void e.setUniform1f("randomSeed2",Math.random());e._mathRandomGenerator&&e._mathRandomGeneratorSeed===e.randomSeed||(e._mathRandomGenerator=function(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(e.randomSeed),e._mathRandomGeneratorSeed=e.randomSeed),e.setUniform1f("randomSeed1",e._mathRandomGenerator()),e.setUniform1f("randomSeed2",e._mathRandomGenerator())},functionMatch:"Math.random()",functionReplace:"nrand(vTexCoord)",functionReturnType:"Number",source:"// https://www.shadertoy.com/view/4t2SDh\n//note: uniformly distributed, normalized rand, [0,1]\nhighp float randomSeedShift = 1.0;\nhighp float slide = 1.0;\nuniform highp float randomSeed1;\nuniform highp float randomSeed2;\n\nhighp float nrand(highp vec2 n) {\n highp float result = fract(sin(dot((n.xy + 1.0) * vec2(randomSeed1 * slide, randomSeed2 * randomSeedShift), vec2(12.9898, 78.233))) * 43758.5453);\n randomSeedShift = result;\n if (randomSeedShift > 0.5) {\n slide += 0.00009; \n } else {\n slide += 0.0009;\n }\n return result;\n}"}}),G=e((e,t)=>{t.exports={fragmentShader:`__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nvarying vec2 vTexCoord;\n\nfloat acosh(float x) {\n return log(x + sqrt(x * x - 1.0));\n}\n\nfloat sinh(float x) {\n return (pow(${Math.E}, x) - pow(${Math.E}, -x)) / 2.0;\n}\n\nfloat asinh(float x) {\n return log(x + sqrt(x * x + 1.0));\n}\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat atanh(float x) {\n x = (x + 1.0) / (x - 1.0);\n if (x < 0.0) {\n return 0.5 * log(-x);\n }\n return 0.5 * log(x);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat cosh(float x) {\n return (pow(${Math.E}, x) + pow(${Math.E}, -x)) / 2.0; \n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat tanh(float x) {\n float e = exp(2.0 * x);\n return (e - 1.0) / (e + 1.0);\n}\n\nfloat trunc(float x) {\n if (x >= 0.0) {\n return floor(x); \n } else {\n return ceil(x);\n }\n}\n\nvec4 _round(vec4 x) {\n return floor(x + 0.5);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x / y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(_round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(_round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;\n if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;\n return 0.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n if (channel == 0) return texel.r * 255.0;\n if (channel == 1) return texel.g * 255.0;\n if (channel == 2) return texel.b * 255.0;\n if (channel == 3) return texel.a * 255.0;\n return 0.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return texel.r;\n if (channel == 1) return texel.g;\n if (channel == 2) return texel.b;\n if (channel == 3) return texel.a;\n return 0.0;\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture2D(tex, st / vec2(texSize));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n \n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nvoid color(sampler2D image) {\n actualColor = texture2D(image, vTexCoord);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),O=e((e,t)=>{t.exports={vertexShader:"__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nattribute vec2 aPos;\nattribute vec2 aTexCoord;\n\nvarying vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),V=e((e,t)=>{function s(e,t={}){const{contextName:s="gl",throwGetError:a,useTrackablePrimitives:o,recording:u=[],variables:l={},onReadPixels:h,onUnrecognizedArgumentLookup:c}=t,p=new Proxy(e,{get:function(t,p){switch(p){case"addComment":return A;case"checkThrowError":return w;case"getReadPixelsVariableName":return m;case"insertVariable":return b;case"reset":return x;case"setIndent":return S;case"toString":return y;case"getContextVariableName":return E}return"function"==typeof e[p]?function(){switch(p){case"getError":return a?u.push(`${g}if (${s}.getError() !== ${s}.NONE) throw new Error('error');`):u.push(`${g}${s}.getError();`),e.getError();case"getExtension":{const t=`${s}Variables${d.length}`;u.push(`${g}const ${t} = ${s}.getExtension('${arguments[0]}');`);const n=e.getExtension(arguments[0]);if(n&&"object"==typeof n){const e=r(n,{getEntity:v,useTrackablePrimitives:o,recording:u,contextName:t,contextVariables:d,variables:l,indent:g,onUnrecognizedArgumentLookup:c});return d.push(e),e}return d.push(null),n}case"readPixels":const t=d.indexOf(arguments[6]);let i;if(-1===t){const e=function(e){if(l)for(const t in l)if(l[t]===e)return t;return null}(arguments[6]);e?(i=e,u.push(`${g}${e}`)):(i=`${s}Variable${d.length}`,d.push(arguments[6]),u.push(`${g}const ${i} = new ${arguments[6].constructor.name}(${arguments[6].length});`))}else i=`${s}Variable${t}`;m=i;const p=[arguments[0],arguments[1],arguments[2],arguments[3],v(arguments[4]),v(arguments[5]),i];return u.push(`${g}${s}.readPixels(${p.join(", ")});`),h&&h(i,p),e.readPixels.apply(e,arguments);case"drawBuffers":return u.push(`${g}${s}.drawBuffers([${n(arguments[0],{contextName:s,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})}]);`),e.drawBuffers(arguments[0])}let t=e[p].apply(e,arguments);switch(typeof t){case"undefined":return void u.push(`${g}${_(p,arguments)};`);case"number":case"boolean":if(o&&-1===d.indexOf(i(t))){u.push(`${g}const ${s}Variable${d.length} = ${_(p,arguments)};`),d.push(t=i(t));break}default:null===t?u.push(`${_(p,arguments)};`):u.push(`${g}const ${s}Variable${d.length} = ${_(p,arguments)};`),d.push(t)}return t}:(f[e[p]]=p,e[p])}}),d=[],f={};let m,g="";return p;function y(){return u.join("\n")}function x(){for(;u.length>0;)u.pop()}function b(e,t){l[e]=t}function v(e){const t=f[e];return t?s+"."+t:e}function S(e){g=" ".repeat(e)}function T(e,t){const r=`${s}Variable${d.length}`;return u.push(`${g}const ${r} = ${t};`),d.push(e),r}function A(e){u.push(`${g}// ${e}`)}function w(){u.push(`${g}(() => {\n${g}const error = ${s}.getError();\n${g}if (error !== ${s}.NONE) {\n${g} const names = Object.getOwnPropertyNames(gl);\n${g} for (let i = 0; i < names.length; i++) {\n${g} const name = names[i];\n${g} if (${s}[name] === error) {\n${g} throw new Error('${s} threw ' + name);\n${g} }\n${g} }\n${g}}\n${g}})();`)}function _(e,t){return`${s}.${e}(${n(t,{contextName:s,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})})`}function E(e){const t=d.indexOf(e);return-1!==t?`${s}Variable${t}`:null}}function r(e,t){const s=new Proxy(e,{get:function(t,s){return"function"==typeof t[s]?function(){if("drawBuffersWEBGL"===s)return h.push(`${p}${a}.drawBuffersWEBGL([${n(arguments[0],{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})}]);`),e.drawBuffersWEBGL(arguments[0]);let t=e[s].apply(e,arguments);switch(typeof t){case"undefined":return void h.push(`${p}${m(s,arguments)};`);case"number":case"boolean":l&&-1===o.indexOf(i(t))?(h.push(`${p}const ${a}Variable${o.length} = ${m(s,arguments)};`),o.push(t=i(t))):(h.push(`${p}const ${a}Variable${o.length} = ${m(s,arguments)};`),o.push(t));break;default:null===t?h.push(`${m(s,arguments)};`):h.push(`${p}const ${a}Variable${o.length} = ${m(s,arguments)};`),o.push(t)}return t}:(r[e[s]]=s,e[s])}}),r={},{contextName:a,contextVariables:o,getEntity:u,useTrackablePrimitives:l,recording:h,variables:c,indent:p,onUnrecognizedArgumentLookup:d}=t;return s;function f(e){return r.hasOwnProperty(e)?`${a}.${r[e]}`:u(e)}function m(e,t){return`${a}.${e}(${n(t,{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})})`}function g(e,t){const s=`${a}Variable${o.length}`;return o.push(e),h.push(`${p}const ${s} = ${t};`),s}}function n(e,t){const{variables:s,onUnrecognizedArgumentLookup:r}=t;return Array.from(e).map(e=>{const n=function(e){if(s)for(const t in s)if(s.hasOwnProperty(t)&&s[t]===e)return t;return r?r(e):null}(e);return n||function(e,t){const{contextName:s,contextVariables:r,getEntity:n,addVariable:i,onUnrecognizedArgumentLookup:a}=t;if(void 0===e)return"undefined";if(null===e)return"null";const o=r.indexOf(e);if(o>-1)return`${s}Variable${o}`;switch(e.constructor.name){case"String":const t=/\n/.test(e),s=/'/.test(e),r=/"/.test(e);return t?"`"+e+"`":s&&!r?'"'+e+'"':"'"+e+"'";case"Number":case"Boolean":return n(e);case"Array":return i(e,`new ${e.constructor.name}([${Array.from(e).join(",")}])`);case"Float32Array":case"Uint8Array":case"Uint16Array":case"Int32Array":return i(e,`new ${e.constructor.name}(${JSON.stringify(Array.from(e))})`);default:if(a){const t=a(e);if(t)return t}throw new Error(`unrecognized argument type ${e.constructor.name}`)}}(e,t)}).join(", ")}function i(e){return new e.constructor(e)}void 0!==t&&(t.exports={glWiretap:s,glExtensionWiretap:r}),"undefined"!=typeof window&&(s.glExtensionWiretap=r,window.glWiretap=s)}),P=e((e,t)=>{const{glWiretap:s}=V(),{utils:r}=i();function n(e){let t=e.toString().replace(/^function /,"");const s=t.indexOf("=>");if(-1!==s&&!/[{]|\bfunction\b/.test(t.slice(0,s))){const e=t.slice(0,s).trim(),r=t.slice(s+2).trim();t=r.startsWith("{")?`${e} ${r}`:`${e} { return ${r}; }`}return t.replace(/utils[.]/g,"/*utils.*/")}function a(e,t){const s="single"===t.precision?e:`new Float32Array(${e}.buffer)`;return t.output[2]?`renderOutput(${s}, ${t.output[0]}, ${t.output[1]}, ${t.output[2]})`:t.output[1]?`renderOutput(${s}, ${t.output[0]}, ${t.output[1]})`:`renderOutput(${s}, ${t.output[0]})`}function o(e,t){const s=e.toArray.toString(),n=!/^function/.test(s);return`() => {\n function framebuffer() { return getReadFramebuffer(); };\n ${r.flattenFunctionToString(`${n?"function ":""}${s}`,{findDependency:(t,s)=>{if("utils"===t)return`const ${s} = ${r[s].toString()};`;if("this"===t)return"framebuffer"===s?"":`${n?"function ":""}${e[s].toString()}`;throw new Error("unhandled fromObject")},thisLookup:(s,r)=>{if("texture"===s)return t;if("context"===s)return r?null:"gl";if(e.hasOwnProperty(s))return JSON.stringify(e[s]);throw new Error(`unhandled thisLookup ${s}`)}})}\n return toArray();\n }`}function u(e,t,s,r,n){if(null===e)return null;if(null===t)return null;switch(typeof e){case"boolean":case"number":return null}if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement)for(let n=0;n{switch(typeof e){case"boolean":return new Boolean(e);case"number":return new Number(e);default:return e}}):null;const c=[],p=[],d=s(i.context,{useTrackablePrimitives:!0,onReadPixels:e=>{if(N.subKernels){if(f){const t=N.subKernels[m++].property;p.push(` result${isNaN(t)?"."+t:`[${t}]`} = ${a(e,N)};`)}else p.push(` const result = { result: ${a(e,N)} };`),f=!0;m===N.subKernels.length&&p.push(" return result;")}else e?p.push(` return ${a(e,N)};`):p.push(" return null;")},onUnrecognizedArgumentLookup:e=>{const t=u(e,N.kernelArguments,[],d,c);if(t)return t;const s=u(e,N.kernelConstants,T?Object.keys(T).map(e=>T[e]):[],d,c);return s||null}});let f=!1,m=0;const{source:g,canvas:y,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:C,argumentTypes:L,constantTypes:D,kernelArguments:F,kernelConstants:$,tactic:R}=i,N=new e(g,{canvas:y,context:d,checkContext:!1,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:C,argumentTypes:L,constantTypes:D,tactic:R});let M=[];if(d.setIndent(2),N.build.apply(N,t),M.push(d.toString()),d.reset(),N.kernelArguments.forEach((e,s)=>{switch(e.type){case"Integer":case"Boolean":case"Number":case"Float":case"Array":case"Array(2)":case"Array(3)":case"Array(4)":case"HTMLCanvas":case"HTMLImage":case"HTMLVideo":case"Input":d.insertVariable(`uploadValue_${e.name}`,e.uploadValue);break;case"HTMLImageArray":for(let r=0;re.varName).join(", ")}) {`),d.setIndent(4),N.run.apply(N,t),N.renderKernels?N.renderKernels():N.renderOutput&&N.renderOutput(),M.push(" /** start setup uploads for kernel values **/"),N.kernelArguments.forEach(e=>{M.push(" "+e.getStringValueHandler().split("\n").join("\n "))}),M.push(" /** end setup uploads for kernel values **/"),M.push(d.toString()),N.renderOutput===N.renderTexture)if(d.reset(),N.renderKernels){const e=N.renderKernels(),t=d.getContextVariableName(N.texture.texture);M.push(` return {\n result: {\n texture: ${t},\n type: '${e.result.type}',\n toArray: ${o(e.result,t)}\n },`);const{subKernels:s,mappedTextures:r}=N;for(let t=0;t"utils"===e?`const ${t} = ${r[t].toString()};`:null,thisLookup:t=>{if("context"===t)return null;if(e.hasOwnProperty(t))return JSON.stringify(e[t]);throw new Error(`unhandled thisLookup ${t}`)}})}(N)),M.push(" innerKernel.getPixels = getPixels;")),M.push(" return innerKernel;");let G=[];return $.forEach(e=>{G.push(`${e.getStringValueHandler()}`)}),`function kernel(settings) {\n const { context, constants } = settings;\n ${G.join("")}\n ${l||""}\n${M.join("\n")}\n}`}}}),B=e((e,t)=>{t.exports={KernelValue:class{constructor(e,t){const{name:s,kernel:r,context:n,checkContext:i,onRequestContextHandle:a,onUpdateValueMismatch:o,origin:u,strictIntegers:l,type:h,tactic:c}=t;if(!s)throw new Error("name not set");if(!h)throw new Error("type not set");if(!u)throw new Error("origin not set");if("user"!==u&&"constants"!==u)throw new Error(`origin must be "user" or "constants" value is "${u}"`);if(!a)throw new Error("onRequestContextHandle is not set");this.name=s,this.origin=u,this.tactic=c,this.varName="constants"===u?`constants.${s}`:s,this.kernel=r,this.strictIntegers=l,this.type=e.type||h,this.size=e.size||null,this.index=null,this.context=n,this.checkContext=null==i||i,this.contextHandle=null,this.onRequestContextHandle=a,this.onUpdateValueMismatch=o,this.forceUploadEachRun=null}get id(){return`${this.origin}_${name}`}getSource(){throw new Error(`"getSource" not defined on ${this.constructor.name}`)}updateValue(e){throw new Error(`"updateValue" not defined on ${this.constructor.name}`)}}}}),z=e((e,t)=>{const{utils:s}=i(),{KernelValue:r}=B();t.exports={WebGLKernelValue:class extends r{constructor(e,t){super(e,t),this.dimensionsId=null,this.sizeId=null,this.initialValueConstructor=e.constructor,this.onRequestTexture=t.onRequestTexture,this.onRequestIndex=t.onRequestIndex,this.uploadValue=null,this.textureSize=null,this.bitRatio=null,this.prevArg=null}get id(){return`${this.origin}_${s.sanitizeName(this.name)}`}setup(){}rebind(){}getTransferArrayType(e){if(Array.isArray(e[0]))return this.getTransferArrayType(e[0]);switch(e.constructor){case Array:case Int32Array:case Int16Array:case Int8Array:return Float32Array;case Uint8ClampedArray:case Uint8Array:case Uint16Array:case Uint32Array:case Float32Array:case Float64Array:return e.constructor}return console.warn("Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros"),e.constructor}getStringValueHandler(){throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`)}getVariablePrecisionString(){return this.kernel.getVariablePrecisionString(this.textureSize||void 0,this.tactic||void 0)}destroy(){}}}}),U=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValue:r}=z();t.exports={WebGLKernelValueBoolean:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const bool ${this.id} = ${e};\n`:`uniform bool ${this.id};\n`}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),K=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValue:r}=z();t.exports={WebGLKernelValueFloat:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?Number.isInteger(e)?`const float ${this.id} = ${s.glslFloatLiteral(e)};\n`:`const float ${this.id} = ${e};\n`:`uniform float ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1f(this.id,this.uploadValue=e)}}}}),W=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValue:r}=z();t.exports={WebGLKernelValueInteger:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?`const int ${this.id} = ${parseInt(e)};\n`:`uniform int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),j=e((e,t)=>{const{WebGLKernelValue:s}=z(),{Input:n}=r();t.exports={WebGLKernelArray:class extends s{rebind(){if(!this.texture||void 0===this.contextHandle||null===this.contextHandle)return;const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D,this.texture)}checkSize(e,t){if(!this.kernel.validate)return;const{maxTextureSize:s}=this.kernel.constructor.features;if(e>s||t>s)throw e>t?new Error(`Argument texture width of ${e} larger than maximum size of ${s} for your GPU`):e{const{utils:s}=i(),{WebGLKernelArray:r}=j();function n(e){return{width:e.width>0?e.width:e.videoWidth,height:e.height>0?e.height:e.videoHeight}}t.exports={WebGLKernelValueHTMLImage:class extends r{constructor(e,t){super(e,t);const{width:s,height:r}=n(e);this.checkSize(s,r),this.dimensions=[s,r,1],this.textureSize=[s,r],this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue=e),this.kernel.setUniform1i(this.id,this.index)}},mediaSize:n}}),X=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueHTMLImage:r,mediaSize:n}=q();t.exports={WebGLKernelValueDynamicHTMLImage:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:s}=n(e);this.checkSize(t,s),this.dimensions=[t,s,1],this.textureSize=[t,s],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),H=e((e,t)=>{const{WebGLKernelValueHTMLImage:s}=q();t.exports={WebGLKernelValueHTMLVideo:class extends s{}}}),Y=e((e,t)=>{const{WebGLKernelValueDynamicHTMLImage:s}=X();t.exports={WebGLKernelValueDynamicHTMLVideo:class extends s{}}}),Z=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleInput:class extends r{constructor(e,t){super(e,t),this.bitRatio=4;let[r,n,i]=e.size;this.dimensions=new Int32Array([r||1,n||1,i||1]),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return s.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}.value, uploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),J=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleInput:r}=Z();t.exports={WebGLKernelValueDynamicSingleInput:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,n]=e.size;this.dimensions=new Int32Array([t||1,r||1,n||1]),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Q=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueUnsignedInput:class extends r{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e);const[r,n,i]=e.size;this.dimensions=new Int32Array([r||1,n||1,i||1]),this.textureSize=s.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e.value),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return s.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}.value, preUploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(value.constructor);const{context:t}=this;s.flattenTo(e.value,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ee=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueUnsignedInput:r}=Q();t.exports={WebGLKernelValueDynamicUnsignedInput:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,n]=e.size;this.dimensions=new Int32Array([t||1,r||1,n||1]),this.textureSize=s.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const i=this.getTransferArrayType(e.value);this.preUploadValue=new i(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),te=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j(),n="Source and destination textures are the same. Use immutable = true and manually cleanup kernel output texture memory with texture.delete()";t.exports={WebGLKernelValueMemoryOptimizedNumberTexture:class extends r{constructor(e,t){super(e,t);const[s,r]=e.size;this.checkSize(s,r),this.dimensions=e.dimensions,this.textureSize=e.size,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:s}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(n);if(t.mappedTextures){const{mappedTextures:s}=t;for(let t=0;t{const{utils:s}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:r}=te();t.exports={WebGLKernelValueDynamicMemoryOptimizedNumberTexture:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),re=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j(),{sameError:n}=te();t.exports={WebGLKernelValueNumberTexture:class extends r{constructor(e,t){super(e,t);const[s,r]=e.size;this.checkSize(s,r);const{size:n,dimensions:i}=e;this.bitRatio=this.getBitRatio(e),this.dimensions=i,this.textureSize=n,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:s}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(n);if(t.mappedTextures){const{mappedTextures:s}=t;for(let t=0;t{const{utils:s}=i(),{WebGLKernelValueNumberTexture:r}=re();t.exports={WebGLKernelValueDynamicNumberTexture:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ie=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.dimensions=s.getDimensions(e,!0),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return s.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!s.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ae=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray:r}=ie();t.exports={WebGLKernelValueDynamicSingleArray:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=s.getDimensions(e,!0),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),oe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray1DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=s.getDimensions(e,!0);this.textureSize=s.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],1,1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return s.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flatten2dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ue=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray1DI:r}=oe();t.exports={WebGLKernelValueDynamicSingleArray1DI:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),le=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray2DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=s.getDimensions(e,!0);this.textureSize=s.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return s.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flatten3dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),he=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray2DI:r}=le();t.exports={WebGLKernelValueDynamicSingleArray2DI:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ce=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueSingleArray3DI:class extends r{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=s.getDimensions(e,!0);this.textureSize=s.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],t[3]]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return s.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flatten4dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),pe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray3DI:r}=ce();t.exports={WebGLKernelValueDynamicSingleArray3DI:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),de=e((e,t)=>{const{WebGLKernelValue:s}=z();t.exports={WebGLKernelValueArray2:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec2 ${this.id} = vec2(${e[0]},${e[1]});\n`:`uniform vec2 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform2fv(this.id,this.uploadValue=e)}}}}),fe=e((e,t)=>{const{WebGLKernelValue:s}=z();t.exports={WebGLKernelValueArray3:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec3 ${this.id} = vec3(${e[0]},${e[1]},${e[2]});\n`:`uniform vec3 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform3fv(this.id,this.uploadValue=e)}}}}),me=e((e,t)=>{const{WebGLKernelValue:s}=z();t.exports={WebGLKernelValueArray4:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec4 ${this.id} = vec4(${e[0]},${e[1]},${e[2]},${e[3]});\n`:`uniform vec4 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform4fv(this.id,this.uploadValue=e)}}}}),ge=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGLKernelValueUnsignedArray:class extends r{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e),this.dimensions=s.getDimensions(e,!0),this.textureSize=s.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return s.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}, preUploadValue_${this.name})`])}getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!s.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ye=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueUnsignedArray:r}=ge();t.exports={WebGLKernelValueDynamicUnsignedArray:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=s.getDimensions(e,!0),this.textureSize=s.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const t=this.getTransferArrayType(e);this.preUploadValue=new t(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),xe=e((e,t)=>{const{WebGLKernelValueBoolean:s}=U(),{WebGLKernelValueFloat:r}=K(),{WebGLKernelValueInteger:n}=W(),{WebGLKernelValueHTMLImage:i}=q(),{WebGLKernelValueDynamicHTMLImage:a}=X(),{WebGLKernelValueHTMLVideo:o}=H(),{WebGLKernelValueDynamicHTMLVideo:u}=Y(),{WebGLKernelValueSingleInput:l}=Z(),{WebGLKernelValueDynamicSingleInput:h}=J(),{WebGLKernelValueUnsignedInput:c}=Q(),{WebGLKernelValueDynamicUnsignedInput:p}=ee(),{WebGLKernelValueMemoryOptimizedNumberTexture:d}=te(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:f}=se(),{WebGLKernelValueNumberTexture:m}=re(),{WebGLKernelValueDynamicNumberTexture:g}=ne(),{WebGLKernelValueSingleArray:y}=ie(),{WebGLKernelValueDynamicSingleArray:x}=ae(),{WebGLKernelValueSingleArray1DI:b}=oe(),{WebGLKernelValueDynamicSingleArray1DI:v}=ue(),{WebGLKernelValueSingleArray2DI:S}=le(),{WebGLKernelValueDynamicSingleArray2DI:T}=he(),{WebGLKernelValueSingleArray3DI:A}=ce(),{WebGLKernelValueDynamicSingleArray3DI:w}=pe(),{WebGLKernelValueArray2:_}=de(),{WebGLKernelValueArray3:E}=fe(),{WebGLKernelValueArray4:I}=me(),{WebGLKernelValueUnsignedArray:k}=ge(),{WebGLKernelValueDynamicUnsignedArray:C}=ye(),L={unsigned:{dynamic:{Boolean:s,Integer:n,Float:r,Array:C,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:p,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:s,Float:r,Integer:n,Array:k,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:c,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}},single:{dynamic:{Boolean:s,Integer:n,Float:r,Array:x,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":v,"Array1D(3)":v,"Array1D(4)":v,"Array2D(2)":T,"Array2D(3)":T,"Array2D(4)":T,"Array3D(2)":w,"Array3D(3)":w,"Array3D(4)":w,Input:h,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:s,Float:r,Integer:n,Array:y,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":b,"Array1D(3)":b,"Array1D(4)":b,"Array2D(2)":S,"Array2D(3)":S,"Array2D(4)":S,"Array3D(2)":A,"Array3D(3)":A,"Array3D(4)":A,Input:l,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}}};t.exports={lookupKernelValueType:function(e,t,s,r){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!s)throw new Error("precision missing");r.type&&(e=r.type);const n=L[s][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===n[e])return null;if(void 0===n[e])throw new Error(`Could not find a KernelValue for ${e}`);return n[e]},kernelValueMaps:L}}),be=e((e,t)=>{const{GLKernel:s}=R(),{FunctionBuilder:r}=o(),{WebGLFunctionNode:n}=N(),{utils:a}=i(),u=M(),{fragmentShader:l}=G(),{vertexShader:h}=O(),{glKernelString:c}=P(),{lookupKernelValueType:p}=xe();let d=null,f=null,m=null,g=null,y=null;const x=[u],b=[],v={};t.exports={WebGLKernel:class extends s{static get isSupported(){return null!==d||(this.setupFeatureChecks(),d=this.isContextMatch(m)),d}static setupFeatureChecks(){"undefined"!=typeof document?f=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(f=new OffscreenCanvas(0,0)),f&&(m=f.getContext("webgl"),m||f instanceof OffscreenCanvas||(m=f.getContext("experimental-webgl")),m&&m.getExtension&&(g={OES_texture_float:m.getExtension("OES_texture_float"),OES_texture_float_linear:m.getExtension("OES_texture_float_linear"),OES_element_index_uint:m.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:m.getExtension("WEBGL_draw_buffers")},y=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGLRenderingContext&&e instanceof WebGLRenderingContext}static getIsTextureFloat(){return Boolean(g.OES_texture_float)}static getIsDrawBuffers(){return Boolean(g.WEBGL_draw_buffers)}static getChannelCount(){return g.WEBGL_draw_buffers?m.getParameter(g.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return m.getParameter(m.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,s,r){return p(e,t,s,r)}static get testCanvas(){return f}static get testContext(){return m}static get features(){return y}static get fragmentShader(){return l}static get vertexShader(){return h}constructor(e,t){super(e,t),this.program=null,this.pipeline=t.pipeline,this.endianness=a.systemEndianness(),this.extensions={},this.argumentTextureCount=0,this.constantTextureCount=0,this.fragShader=null,this.vertShader=null,this.drawBuffersMap=null,this.maxTexSize=null,this.onRequestSwitchKernel=null,this.texture=null,this.mappedTextures=null,this.mergeSettings(e.settings||t),this.threadDim=null,this.framebuffer=null,this.buffer=null,this.textureCache=[],this.programUniformLocationCache={},this.uniform1fCache={},this.uniform1iCache={},this.uniform2fCache={},this.uniform2fvCache={},this.uniform2ivCache={},this.uniform3fvCache={},this.uniform3ivCache={},this.uniform4fvCache={},this.uniform4ivCache={}}initCanvas(){if("undefined"!=typeof document){const e=document.createElement("canvas");return e.width=2,e.height=2,e}if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(0,0)}initContext(){const e={alpha:!1,depth:!1,antialias:!1};return this.canvas.getContext("webgl",e)||this.canvas.getContext("experimental-webgl",e)}initPlugins(e){const t=[],{source:s}=this;if("string"==typeof s)for(let e=0;ee===r.name)&&t.push(r)}return t}initExtensions(){this.extensions={OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:this.context.getExtension("WEBGL_color_buffer_float")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if(!0===this.optimizeFloatMemory&&!t.isTextureFloat)throw new Error("Float textures are not supported");if("single"===this.precision&&!t.isFloatRead)throw new Error("Single precision not supported");if(this.graphical||null!==this.precision||(this.precision=t.isTextureFloat&&t.isFloatRead?"single":"unsigned"),this.subKernels&&this.subKernels.length>0&&!this.extensions.WEBGL_draw_buffers)throw new Error("could not instantiate draw buffers extension");if(null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"precision"===this.precision&&(this.precision="unsigned",console.warn("Cannot use graphical mode and single precision at the same time")),void(this.texSize=a.clone(this.output))}null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}updateMaxTexSize(){const{texSize:e,canvas:t}=this;if(null===this.maxTexSize){let s=b.indexOf(t);-1===s&&(s=b.length,b.push(t),v[s]=[e[0],e[1]]),this.maxTexSize=v[s]}this.maxTexSize[0]this.argumentNames.length)throw new Error("too many arguments for kernel");const{context:s}=this;let r=0;const n=()=>this.createTexture(),i=()=>this.constantTextureCount+r++,o=e=>{this.switchKernels({type:"argumentMismatch",needed:e})},u=()=>s.TEXTURE0+this.constantTextureCount+this.argumentTextureCount++;for(let r=0;rthis.createTexture(),onRequestIndex:()=>r++,onRequestContextHandle:()=>t.TEXTURE0+this.constantTextureCount++});this.constantBitRatios[n]=l.bitRatio,this.kernelConstants.push(l),l.setup(),l.forceUploadEachRun&&this.forceUploadKernelConstants.push(l)}}build(){if(this.built)return;if(this.initExtensions(),this.validateSettings(arguments),this.setupConstants(arguments),this.fallbackRequested)return;if(this.setupArguments(arguments),this.fallbackRequested)return;this.updateMaxTexSize(),this.translateSource();const e=this.pickRenderStrategy(arguments);if(e)return e;const{texSize:t,context:s,canvas:r}=this;s.enable(s.SCISSOR_TEST),this.pipeline&&this.precision,s.viewport(0,0,this.maxTexSize[0],this.maxTexSize[1]),r.width=this.maxTexSize[0],r.height=this.maxTexSize[1];const n=this.threadDim=Array.from(this.output);for(;n.length<3;)n.push(1);const i=this.getVertexShader(arguments),a=s.createShader(s.VERTEX_SHADER);s.shaderSource(a,i),s.compileShader(a),this.vertShader=a;const o=this.getFragmentShader(arguments),u=s.createShader(s.FRAGMENT_SHADER);if(s.shaderSource(u,o),s.compileShader(u),this.fragShader=u,this.debug&&(console.log("GLSL Shader Output:"),console.log(o)),!s.getShaderParameter(a,s.COMPILE_STATUS))throw new Error("Error compiling vertex shader: "+s.getShaderInfoLog(a));if(!s.getShaderParameter(u,s.COMPILE_STATUS))throw new Error("Error compiling fragment shader: "+s.getShaderInfoLog(u));const l=this.program=s.createProgram();s.attachShader(l,a),s.attachShader(l,u),s.linkProgram(l),this.framebuffer=s.createFramebuffer(),this.framebuffer.width=t[0],this.framebuffer.height=t[1],this.rawValueFramebuffers={};const h=new Float32Array([-1,-1,1,-1,-1,1,1,1]),c=new Float32Array([0,0,1,0,0,1,1,1]),p=h.byteLength;let d=this.buffer;d?s.bindBuffer(s.ARRAY_BUFFER,d):(d=this.buffer=s.createBuffer(),s.bindBuffer(s.ARRAY_BUFFER,d),s.bufferData(s.ARRAY_BUFFER,h.byteLength+c.byteLength,s.STATIC_DRAW)),s.bufferSubData(s.ARRAY_BUFFER,0,h),s.bufferSubData(s.ARRAY_BUFFER,p,c);const f=s.getAttribLocation(this.program,"aPos");-1!==f&&(s.enableVertexAttribArray(f),s.vertexAttribPointer(f,2,s.FLOAT,!1,0,0));const m=s.getAttribLocation(this.program,"aTexCoord");-1!==m&&(s.enableVertexAttribArray(m),s.vertexAttribPointer(m,2,s.FLOAT,!1,0,p)),s.bindFramebuffer(s.FRAMEBUFFER,this.framebuffer);let g=0;s.useProgram(this.program);for(let e in this.constants)this.kernelConstants[g++].updateValue(this.constants[e]);this._setupOutputTexture(),null!==this.subKernels&&this.subKernels.length>0&&(this._mappedTextureSwitched={},this._setupSubOutputTextures()),this.buildSignature(arguments),this.built=!0}translateSource(){const e=r.fromKernel(this,n,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}setupReturnTypes(e){if(this.graphical||this.returnType||(this.returnType=e.getKernelResultType()),this.subKernels&&this.subKernels.length>0)for(let t=0;te.source&&this.source.match(e.functionMatch)?e.source:"").join("\n"):"\n"}_getConstantsString(){const e=[],{threadDim:t,texSize:s}=this;return this.dynamicOutput?e.push("uniform ivec3 uOutputDim","uniform ivec2 uTexSize"):e.push(`ivec3 uOutputDim = ivec3(${t[0]}, ${t[1]}, ${t[2]})`,`ivec2 uTexSize = ivec2(${s[0]}, ${s[1]})`),a.linesToString(e)}_getTextureCoordinate(){const e=this.subKernels;return null===e||e.length<1?"varying vec2 vTexCoord;\n":"out vec2 vTexCoord;\n"}_getDecode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getEncode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getDivideWithIntegerCheckString(){return this.fixIntegerDivisionAccuracy?"float divWithIntCheck(float x, float y) {\n if (floor(x) == x && floor(y) == y) {\n float q = floor(x / y + 0.5);\n if (y * q == x) {\n return q;\n }\n }\n return x / y;\n}\n\nfloat integerCorrectionModulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -(number - (divisor * floor(divWithIntCheck(number, divisor))));\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return number - (divisor * floor(divWithIntCheck(number, divisor)));\n}":""}_getMainArgumentsString(e){const t=[],{argumentNames:s}=this;for(let r=0;r{if(t.hasOwnProperty(s))return t[s];throw`unhandled artifact ${s}`})}getFragmentShader(e){return null!==this.compiledFragmentShader?this.compiledFragmentShader:this.compiledFragmentShader=this.replaceArtifacts(this.constructor.fragmentShader,this._getFragShaderArtifactMap(e))}getVertexShader(e){return null!==this.compiledVertexShader?this.compiledVertexShader:this.compiledVertexShader=this.replaceArtifacts(this.constructor.vertexShader,this._getVertShaderArtifactMap(e))}toString(){const e=a.linesToString(["const gl = context"]);return c(this.constructor,arguments,this,e)}destroy(e){if(!this.context)return;this.buffer&&this.context.deleteBuffer(this.buffer),this.framebuffer&&this.context.deleteFramebuffer(this.framebuffer);for(const e in this.rawValueFramebuffers){for(const t in this.rawValueFramebuffers[e])this.context.deleteFramebuffer(this.rawValueFramebuffers[e][t]),delete this.rawValueFramebuffers[e][t];delete this.rawValueFramebuffers[e]}if(this.vertShader&&this.context.deleteShader(this.vertShader),this.fragShader&&this.context.deleteShader(this.fragShader),this.program&&this.context.deleteProgram(this.program),this.texture){this.texture.delete();const e=this.textureCache.indexOf(this.texture.texture);e>-1&&this.textureCache.splice(e,1),this.texture=null}if(this.mappedTextures&&this.mappedTextures.length){for(let e=0;e-1&&this.textureCache.splice(s,1)}this.mappedTextures=null}if(this.kernelArguments)for(let e=0;e0;){const e=this.textureCache.pop();this.context.deleteTexture(e)}if(e){const e=b.indexOf(this.canvas);e>=0&&(b[e]=null,v[e]=null)}if(this.destroyExtensions(),delete this.context,delete this.canvas,!this.gpu)return;const t=this.gpu.kernels.indexOf(this);-1!==t&&this.gpu.kernels.splice(t,1)}destroyExtensions(){this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("WEBGL_lose_context");t&&t.loseContext()}toJSON(){const e=super.toJSON();return e.functionNodes=r.fromKernel(this,n).toJSON(),e.settings.threadDim=this.threadDim,e}}}}),ve=e((e,t)=>{const s=d(),{WebGLKernel:r}=be(),{glKernelString:n}=P();let i=null,a=null,o=null,u=null,l=null;t.exports={HeadlessGLKernel:class extends r{static get isSupported(){return null!==i||(this.setupFeatureChecks(),i=null!==o),i}static setupFeatureChecks(){if(a=null,u=null,"function"==typeof s)try{if(o=s(2,2,{preserveDrawingBuffer:!0}),!o||!o.getExtension)return;u={STACKGL_resize_drawingbuffer:o.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:o.getExtension("STACKGL_destroy_context"),OES_texture_float:o.getExtension("OES_texture_float"),OES_texture_float_linear:o.getExtension("OES_texture_float_linear"),OES_element_index_uint:o.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:o.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:o.getExtension("WEBGL_color_buffer_float")},l=this.getFeatures()}catch(e){console.warn(e)}}static isContextMatch(e){try{return"ANGLE"===e.getParameter(e.RENDERER)}catch(e){return!1}}static getIsTextureFloat(){return Boolean(u.OES_texture_float)}static getIsDrawBuffers(){return Boolean(u.WEBGL_draw_buffers)}static getChannelCount(){return u.WEBGL_draw_buffers?o.getParameter(u.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return o.getParameter(o.MAX_TEXTURE_SIZE)}static get testCanvas(){return a}static get testContext(){return o}static get features(){return l}initCanvas(){return{}}initContext(){return s(2,2,{preserveDrawingBuffer:!0})}initExtensions(){this.extensions={STACKGL_resize_drawingbuffer:this.context.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:this.context.getExtension("STACKGL_destroy_context"),OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers")}}build(){super.build.apply(this,arguments),this.fallbackRequested||this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1])}destroyExtensions(){this.extensions.STACKGL_resize_drawingbuffer=null,this.extensions.STACKGL_destroy_context=null,this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("STACKGL_destroy_context");t&&t.destroy&&t.destroy()}toString(){return n(this.constructor,arguments,this,"const gl = context || require('gl')(1, 1);\n"," if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n")}setOutput(e){return super.setOutput(e),this.graphical&&this.extensions.STACKGL_resize_drawingbuffer&&this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1]),this}}}}),Se=e((e,t)=>{const{utils:s}=i(),{WebGLFunctionNode:r}=N();t.exports={WebGL2FunctionNode:class extends r{astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),n=s.sanitizeName(e.name);if("Infinity"===e.name)t.push("intBitsToFloat(2139095039)");else if("Boolean"===r)if(this.argumentNames.indexOf(n)>-1){const s=this.markupUserName(e.name);t.push(s.startsWith("cellShadow_")?s:`bool(${s})`)}else t.push(`user_${n}`);else t.push(this.markupUserName(e.name));return t}}}}),Te=e((e,t)=>{t.exports={fragmentShader:`#version 300 es\n__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n__SAMPLER_2D_ARRAY_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nin vec2 vTexCoord;\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x/y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n return texel[channel] * 255.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n index = index / 4;\n vec4 texel = texture(tex, st / vec2(texSize));\n return texel[channel];\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, st / vec2(texSize));\n}\n\nvec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, vec3(st / vec2(texSize), z));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n\n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),Ae=e((e,t)=>{t.exports={vertexShader:"#version 300 es\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nin vec2 aPos;\nin vec2 aTexCoord;\n\nout vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),we=e((e,t)=>{const{WebGLKernelValueBoolean:s}=U();t.exports={WebGL2KernelValueBoolean:class extends s{}}}),_e=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueFloat:r}=K();t.exports={WebGL2KernelValueFloat:class extends r{}}}),Ee=e((e,t)=>{const{WebGLKernelValueInteger:s}=W();t.exports={WebGL2KernelValueInteger:class extends s{getSource(e){const t=this.getVariablePrecisionString();return"constants"===this.origin?`const ${t} int ${this.id} = ${parseInt(e)};\n`:`uniform ${t} int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),Ie=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueHTMLImage:r}=q();t.exports={WebGL2KernelValueHTMLImage:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),ke=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueDynamicHTMLImage:r}=X();t.exports={WebGL2KernelValueDynamicHTMLImage:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Ce=e((e,t)=>{const{utils:s}=i(),{WebGLKernelArray:r}=j();t.exports={WebGL2KernelValueHTMLImageArray:class extends r{constructor(e,t){super(e,t),this.checkSize(e[0].width,e[0].height),this.dimensions=[e[0].width,e[0].height,e.length],this.textureSize=[e[0].width,e[0].height]}defineTexture(){const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D_ARRAY,this.texture),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MIN_FILTER,e.NEAREST)}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D_ARRAY,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage3D(t.TEXTURE_2D_ARRAY,0,t.RGBA,e[0].width,e[0].height,e.length,0,t.RGBA,t.UNSIGNED_BYTE,null);for(let s=0;s{const{utils:s}=i(),{WebGL2KernelValueHTMLImageArray:r}=Ce();t.exports={WebGL2KernelValueDynamicHTMLImageArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:s}=e[0];this.checkSize(t,s),this.dimensions=[t,s,e.length],this.textureSize=[t,s],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),De=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueHTMLImage:r}=Ie();t.exports={WebGL2KernelValueHTMLVideo:class extends r{}}}),Fe=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueDynamicHTMLImage:r}=ke();t.exports={WebGL2KernelValueDynamicHTMLVideo:class extends r{}}}),$e=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleInput:r}=Z();t.exports={WebGL2KernelValueSingleInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;s.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Re=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueSingleInput:r}=$e();t.exports={WebGL2KernelValueDynamicSingleInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,r,n]=e.size;this.dimensions=new Int32Array([t||1,r||1,n||1]),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ne=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueUnsignedInput:r}=Q();t.exports={WebGL2KernelValueUnsignedInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Me=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueDynamicUnsignedInput:r}=ee();t.exports={WebGL2KernelValueDynamicUnsignedInput:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Ge=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:r}=te();t.exports={WebGL2KernelValueMemoryOptimizedNumberTexture:class extends r{getSource(){const{id:e,sizeId:t,textureSize:r,dimensionsId:n,dimensions:i}=this,a=this.getVariablePrecisionString();return s.linesToString([`uniform sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${r[0]}, ${r[1]})`,`${a} ivec3 ${n} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Oe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:r}=se();t.exports={WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:class extends r{getSource(){return s.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}}}}),Ve=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueNumberTexture:r}=re();t.exports={WebGL2KernelValueNumberTexture:class extends r{getSource(){const{id:e,sizeId:t,textureSize:r,dimensionsId:n,dimensions:i}=this,a=this.getVariablePrecisionString();return s.linesToString([`uniform ${a} sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${r[0]}, ${r[1]})`,`${a} ivec3 ${n} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Pe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueDynamicNumberTexture:r}=ne();t.exports={WebGL2KernelValueDynamicNumberTexture:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Be=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray:r}=ie();t.exports={WebGL2KernelValueSingleArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!s.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ze=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueSingleArray:r}=Be();t.exports={WebGL2KernelValueDynamicSingleArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=s.getDimensions(e,!0),this.textureSize=s.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ue=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray1DI:r}=oe();t.exports={WebGL2KernelValueSingleArray1DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Ke=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueSingleArray1DI:r}=Ue();t.exports={WebGL2KernelValueDynamicSingleArray1DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),We=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray2DI:r}=le();t.exports={WebGL2KernelValueSingleArray2DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),je=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueSingleArray2DI:r}=We();t.exports={WebGL2KernelValueDynamicSingleArray2DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),qe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueSingleArray3DI:r}=ce();t.exports={WebGL2KernelValueSingleArray3DI:class extends r{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;s.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Xe=e((e,t)=>{const{utils:s}=i(),{WebGL2KernelValueSingleArray3DI:r}=qe();t.exports={WebGL2KernelValueDynamicSingleArray3DI:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),He=e((e,t)=>{const{WebGLKernelValueArray2:s}=de();t.exports={WebGL2KernelValueArray2:class extends s{}}}),Ye=e((e,t)=>{const{WebGLKernelValueArray3:s}=fe();t.exports={WebGL2KernelValueArray3:class extends s{}}}),Ze=e((e,t)=>{const{WebGLKernelValueArray4:s}=me();t.exports={WebGL2KernelValueArray4:class extends s{}}}),Je=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueUnsignedArray:r}=ge();t.exports={WebGL2KernelValueUnsignedArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Qe=e((e,t)=>{const{utils:s}=i(),{WebGLKernelValueDynamicUnsignedArray:r}=ye();t.exports={WebGL2KernelValueDynamicUnsignedArray:class extends r{getSource(){const e=this.getVariablePrecisionString();return s.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),et=e((e,t)=>{const{WebGL2KernelValueBoolean:s}=we(),{WebGL2KernelValueFloat:r}=_e(),{WebGL2KernelValueInteger:n}=Ee(),{WebGL2KernelValueHTMLImage:i}=Ie(),{WebGL2KernelValueDynamicHTMLImage:a}=ke(),{WebGL2KernelValueHTMLImageArray:o}=Ce(),{WebGL2KernelValueDynamicHTMLImageArray:u}=Le(),{WebGL2KernelValueHTMLVideo:l}=De(),{WebGL2KernelValueDynamicHTMLVideo:h}=Fe(),{WebGL2KernelValueSingleInput:c}=$e(),{WebGL2KernelValueDynamicSingleInput:p}=Re(),{WebGL2KernelValueUnsignedInput:d}=Ne(),{WebGL2KernelValueDynamicUnsignedInput:f}=Me(),{WebGL2KernelValueMemoryOptimizedNumberTexture:m}=Ge(),{WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:g}=Oe(),{WebGL2KernelValueNumberTexture:y}=Ve(),{WebGL2KernelValueDynamicNumberTexture:x}=Pe(),{WebGL2KernelValueSingleArray:b}=Be(),{WebGL2KernelValueDynamicSingleArray:v}=ze(),{WebGL2KernelValueSingleArray1DI:S}=Ue(),{WebGL2KernelValueDynamicSingleArray1DI:T}=Ke(),{WebGL2KernelValueSingleArray2DI:A}=We(),{WebGL2KernelValueDynamicSingleArray2DI:w}=je(),{WebGL2KernelValueSingleArray3DI:_}=qe(),{WebGL2KernelValueDynamicSingleArray3DI:E}=Xe(),{WebGL2KernelValueArray2:I}=He(),{WebGL2KernelValueArray3:k}=Ye(),{WebGL2KernelValueArray4:C}=Ze(),{WebGL2KernelValueUnsignedArray:L}=Je(),{WebGL2KernelValueDynamicUnsignedArray:D}=Qe(),F={unsigned:{dynamic:{Boolean:s,Integer:n,Float:r,Array:D,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:f,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:s,Float:r,Integer:n,Array:L,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:d,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:g,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}},single:{dynamic:{Boolean:s,Integer:n,Float:r,Array:v,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":T,"Array1D(3)":T,"Array1D(4)":T,"Array2D(2)":w,"Array2D(3)":w,"Array2D(4)":w,"Array3D(2)":E,"Array3D(3)":E,"Array3D(4)":E,Input:p,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:s,Float:r,Integer:n,Array:b,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":S,"Array1D(3)":S,"Array1D(4)":S,"Array2D(2)":A,"Array2D(3)":A,"Array2D(4)":A,"Array3D(2)":_,"Array3D(3)":_,"Array3D(4)":_,Input:c,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:m,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}}};t.exports={kernelValueMaps:F,lookupKernelValueType:function(e,t,s,r){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!s)throw new Error("precision missing");r.type&&(e=r.type);const n=F[s][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===n[e])return null;if(void 0===n[e])throw new Error(`Could not find a KernelValue for ${e}`);return n[e]}}}),tt=e((e,t)=>{const{WebGLKernel:s}=be(),{WebGL2FunctionNode:r}=Se(),{FunctionBuilder:n}=o(),{utils:a}=i(),{fragmentShader:u}=Te(),{vertexShader:l}=Ae(),{lookupKernelValueType:h}=et();let c=null,p=null,d=null,f=null;t.exports={WebGL2Kernel:class extends s{static get isSupported(){return null!==c||(this.setupFeatureChecks(),c=this.isContextMatch(d)),c}static setupFeatureChecks(){"undefined"!=typeof document?p=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(p=new OffscreenCanvas(0,0)),p&&(d=p.getContext("webgl2"),d&&d.getExtension&&(d.getExtension("EXT_color_buffer_float"),d.getExtension("OES_texture_float_linear"),f=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext}static getFeatures(){const e=this.testContext;return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),kernelMap:!0,isTextureFloat:!0,isDrawBuffers:!0,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static getIsTextureFloat(){return!0}static getChannelCount(){return d.getParameter(d.MAX_DRAW_BUFFERS)}static getMaxTextureSize(){return d.getParameter(d.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,s,r){return h(e,t,s,r)}static get testCanvas(){return p}static get testContext(){return d}static get features(){return f}static get fragmentShader(){return u}static get vertexShader(){return l}initContext(){return this.canvas.getContext("webgl2",{alpha:!1,depth:!1,antialias:!1})}initExtensions(){this.extensions={EXT_color_buffer_float:this.context.getExtension("EXT_color_buffer_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if("single"===this.precision&&!t.isFloatRead)throw new Error("Float texture outputs are not supported");if(this.graphical||null!==this.precision||(this.precision=t.isFloatRead?"single":"unsigned"),null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"single"===this.precision&&(console.warn("Cannot use graphical mode and single precision at the same time"),this.precision="unsigned"),void(this.texSize=a.clone(this.output))}!this.graphical&&null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}translateSource(){const e=n.fromKernel(this,r,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}drawBuffers(){this.context.drawBuffers(this.drawBuffersMap)}getTextureFormat(){const{context:e}=this;switch(this.getInternalFormat()){case e.R32F:return e.RED;case e.RG32F:return e.RG;case e.RGBA32F:case e.RGBA:return e.RGBA;default:throw new Error("Unknown internal format")}}renderValues(){return void 0===this._tightRead&&this._detectTightRead(),super.renderValues()}renderKernelsToArrays(){return void 0===this._tightRead&&this._detectTightRead(),super.renderKernelsToArrays()}readFloatPixelsToFloat32Array(){if(!this._tightRead)return super.readFloatPixelsToFloat32Array();const{texSize:e,context:t}=this,s=e[0],r=e[1],n=new Float32Array(s*r);return t.readPixels(0,0,s,r,t.RED,t.FLOAT,n),n}renderOutputAsync(){return this.renderOutput!==this.renderValues?Promise.resolve(this.renderOutput()):this.renderValuesAsync()}renderValuesAsync(){void 0===this._tightRead&&this._detectTightRead();const e=this.formatValues,[t,s,r]=this.output;return this.transferValuesAsync().then(n=>e(n,t,s,r))}transferValuesAsync(){const{texSize:e,context:t}=this,s=e[0],r=e[1];let n,i,a;"single"===this.precision?(n=this._tightRead?t.RED:t.RGBA,i=t.FLOAT,a=new Float32Array(s*r*(this._tightRead?1:4))):(n=t.RGBA,i=t.UNSIGNED_BYTE,a=new Uint8Array(s*r*4));const o=t.createBuffer();t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.bufferData(t.PIXEL_PACK_BUFFER,a.byteLength,t.STREAM_READ),t.readPixels(0,0,s,r,n,i,0),t.bindBuffer(t.PIXEL_PACK_BUFFER,null);const u=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);return t.flush(),this._pollFence(u).then(()=>(t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.getBufferSubData(t.PIXEL_PACK_BUFFER,0,a),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),t.deleteBuffer(o),"single"===this.precision?a:new Float32Array(a.buffer)),e=>{throw t.deleteBuffer(o),e})}_pollFence(e){const t=this.context;return new Promise((s,r)=>{let n,i=null;"undefined"!=typeof MessageChannel?(i=new MessageChannel,i.port1.onmessage=()=>o(),n=()=>i.port2.postMessage(0)):n=()=>setTimeout(o,0);const a=(s,r)=>{t.deleteSync(e),i&&(i.port1.close(),i.port2.close()),s(r)},o=()=>{if(t.isContextLost())return a(r,new Error("WebGL context lost while awaiting kernel result"));const i=t.clientWaitSync(e,0,0);return i===t.ALREADY_SIGNALED||i===t.CONDITION_SATISFIED?a(s):i===t.WAIT_FAILED?a(r,new Error("clientWaitSync failed while awaiting kernel result")):void n()};o()})}_detectTightRead(){const e=this.context;this._tightRead=!1,e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t="Number"===this.returnType||"Float"===this.returnType||"Integer"===this.returnType||"LiteralInteger"===this.returnType;if("single"===this.precision&&!this.optimizeFloatMemory&&!this.graphical&&t&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)===e.RED&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)===e.FLOAT){if(this.formatValues===a.erectFloat)this.formatValues=a.erectMemoryOptimizedFloat;else if(this.formatValues===a.erect2DFloat)this.formatValues=a.erectMemoryOptimized2DFloat;else if(this.formatValues===a.erect3DFloat)this.formatValues=a.erectMemoryOptimized3DFloat;else if(this.formatValues!==a.erectMemoryOptimizedFloat&&this.formatValues!==a.erectMemoryOptimized2DFloat&&this.formatValues!==a.erectMemoryOptimized3DFloat)return;this._tightRead=!0}}getInternalFormat(){const{context:e}=this;if("single"===this.precision)switch(this.returnType){case"Number":case"Float":case"Integer":return this.optimizeFloatMemory?e.RGBA32F:e.R32F;case"Array(2)":return e.RG32F;case"Array(3)":case"Array(4)":return e.RGBA32F;default:throw new Error("Unhandled return type")}return e.RGBA}_setupOutputTexture(){const e=this.context;if(this.texture)return e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0),void(this._tightRead=void 0);e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t=e.createTexture(),s=this.texSize;e.activeTexture(e.TEXTURE0+this.constantTextureCount+this.argumentTextureCount),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);const r=this.getInternalFormat();"single"===this.precision?e.texStorage2D(e.TEXTURE_2D,1,r,s[0],s[1]):e.texImage2D(e.TEXTURE_2D,0,r,s[0],s[1],0,r,e.UNSIGNED_BYTE,null),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),this.texture=new this.TextureConstructor({texture:t,size:s,dimensions:this.threadDim,output:this.output,context:this.context,internalFormat:this.getInternalFormat(),textureFormat:this.getTextureFormat(),kernel:this}),this._tightRead=void 0}_setupSubOutputTextures(){const e=this.context;if(this.mappedTextures){for(let t=0;t{const{utils:s}=i(),{FunctionNode:r}=l();const n={Number:"f32",Float:"f32",Integer:"i32",LiteralInteger:"f32",Boolean:"bool","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4"},a={"===":"==","!==":"!="},o=["x","y","z","w"],u={pow:"_pow",round:"_round"},h={ceil:!0,floor:!0,_round:!0};t.exports={WGSLFunctionNode:class extends r{get requiresSequenceFreeForInit(){return!0}wgslFloat(e){if(e===1/0)return"0x1.fffffep+127";if(e===-1/0)return"-0x1.fffffep+127";if(e>34028234663852886e22)return"0x1.fffffep+127";if(e<-34028234663852886e22)return"-0x1.fffffep+127";const t=`${e}`;return-1!==t.indexOf(".")||-1!==t.indexOf("e")||-1!==t.indexOf("E")?t:`${t}.0`}wgslInt(e){return`${Math.round(e)}`}mangleFunctionName(e){return`fn_${s.sanitizeName(e)}`}getLookupType(e){return"WebGPUBuffer"===e?"Number":super.getLookupType(e)}astUpdateExpression(e,t){return this.astGeneric(e.argument,t),t.push(e.operator),t}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const s=this.getType(e.consequent),r=this.getType(e.alternate);if(null===s&&null===r)return t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t;let n="LiteralInteger"===s?"Number":s;"Integer"!==n||"Number"!==r&&"Float"!==r||(n="Number");const i=e=>{const s=this.getType(e);switch(n){case"Number":case"Float":"Integer"===s?this.castValueToFloat(e,t):"LiteralInteger"===s?this.castLiteralToFloat(e,t):this.astGeneric(e,t);break;case"Integer":"Number"===s||"Float"===s?this.castValueToInteger(e,t):"LiteralInteger"===s?this.castLiteralToInteger(e,t):this.astGeneric(e,t);break;default:this.astGeneric(e,t)}};return t.push("select("),i(e.alternate),t.push(", "),i(e.consequent),t.push(", "),this.astGeneric(e.test,t),t.push(")"),t}astFunction(e,t){if(this.isRootKernel){for(let s=0;s0&&t.push(", ");let a=this.argumentTypes[this.argumentNames.indexOf(i)];if(!a)throw this.astErrorOutput(`Unknown argument ${i} type`,e);"LiteralInteger"===a&&(this.argumentTypes[r]=a="Number");const o=n[a];if(!o)throw this.astErrorOutput(`WebGPU backend does not yet support ${a} arguments to helper functions`,e);t.push(`user_${s.sanitizeName(i)} : ${o}`)}t.push(")"),i&&t.push(` -> ${i}`),t.push(" {\n");for(let s=0;s>":!0,">>>":!0}[e.operator])return null;const s=e=>{switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer")}};return t.push("("),">>>"===e.operator?(t.push("bitcast(bitcast("),s(e.left),t.push(") >> u32("),s(e.right),t.push("))")):"<<"===e.operator||">>"===e.operator?(s(e.left),t.push(` ${e.operator} u32(`),s(e.right),t.push(")")):(s(e.left),t.push(` ${e.operator} `),s(e.right)),t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){if("~"!==e.operator)return null;switch(t.push("~("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)?t:"+"===e.operator?(this.astGeneric(e.argument,t),t):(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t)}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("f32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const r=this.getType(e),n=s.sanitizeName(e.name);return"Infinity"===e.name?(t.push("0x1.fffffep+127"),t):!this.isRootKernel||-1===this.argumentNames.indexOf(e.name)||"Number"!==r&&"Float"!==r&&"Integer"!==r&&"Boolean"!==r?(t.push(`user_${n}`),t):("Boolean"===r?t.push(`bool(params.user_${n})`):t.push(`params.user_${n}`),t)}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const s=[],r=[],n=[],i=[];let a=null;if(e.init){const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,s);for(let e=0;e0&&t.push(s.join(""),"\n"),t.push(`for (var ${e} : i32 = 0;${e}0&&t.push(`if (!(${r.join("")})) { break; }\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const s=this.getInternalVariableName("safeI");return t.push(`for (var ${s} : i32 = 0;${s}{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const s in e)if("loc"!==s&&"range"!==s&&"parent"!==s&&t(e[s]))return!0;return!1};if(t(s[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",s[e])}for(let e=0;ee+1){u=!0,this.astSwitchCaseConsequent(r[e].consequent,o);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(r[e].consequent,t),t.push("\n}")}return u&&(t.push(" else {"),t.push(o.join("")),t.push("}")),t.push("\n"),t}astThisExpression(e,t){return t.push("this"),t}astSequenceExpression(e,t){const{expressions:s}=e;if(1===s.length)return this.astGeneric(s[0],t),t;throw this.astErrorOutput("WebGPU backend does not yet support the comma operator",e)}astMemberExpression(e,t){const{property:r,name:i,signature:a,origin:o,type:u,xProperty:l,yProperty:h,zProperty:c}=this.getMemberExpressionDetails(e);switch(a){case"value.thread.value":case"this.thread.value":if("x"!==i&&"y"!==i&&"z"!==i)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`i32(threadGid.${i})`),t;case"this.output.value":{const s={x:0,y:1,z:2}[i];if(void 0===s)throw this.astErrorOutput("Unexpected expression",e);if(this.dynamicOutput){const e=`params.output${i.toUpperCase()}`;this.isState("casting-to-float")?t.push(`f32(${e})`):t.push(`i32(${e})`)}else this.isState("casting-to-integer")?t.push(`${this.output[s]}`):t.push(`${this.output[s]}.0`);return t}case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===o)return t.push(this.wgslFloat(Math[i])),t;switch(r){case"r":return t.push(`user_${s.sanitizeName(i)}.x`),t;case"g":return t.push(`user_${s.sanitizeName(i)}.y`),t;case"b":return t.push(`user_${s.sanitizeName(i)}.z`),t;case"a":return t.push(`user_${s.sanitizeName(i)}.w`),t}break;case"this.constants.value":{const s=this.constants[i];switch(u){case"Integer":return this.isState("casting-to-float")?t.push(this.wgslFloat(s)):t.push(this.wgslInt(s)),t;case"Number":case"Float":return this.isState("casting-to-integer")?t.push(this.wgslInt(s)):t.push(this.wgslFloat(s)),t;case"Boolean":return t.push(s?"true":"false"),t;case"Array(2)":case"Array(3)":case"Array(4)":{const e=parseInt(u.substring(6),10),r=[];for(let t=0;t4)throw this.astErrorOutput("this.color takes (r, g, b) or (r, g, b, a)",e);t.push("kernelColor(data_index");for(let s=0;s0&&t.push(", "),n){case"Integer":this.castValueToFloat(r,t);break;case"LiteralInteger":this.castLiteralToFloat(r,t);break;default:this.astGeneric(r,t)}}else{const n=this.lookupFunctionArgumentTypes(r)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(r,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("i32("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("f32("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.astGeneric(a,t);continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){"Identifier"===a.type?t.push(`user_${s.sanitizeName(a.name)}`):this.astGeneric(a,t);continue}break;case"Array":case"Array2D":case"Array3D":case"Input":case"WebGPUBuffer":throw this.astErrorOutput("WebGPU backend does not yet support array arguments to helper functions",e)}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),a&&t.push(")"),t}astArrayExpression(e,t){switch(this.getType(e)){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":throw this.astErrorOutput("WebGPU backend does not yet support Matrix types",e)}const s=e.elements.length;t.push(`vec${s}(`);for(let r=0;r0&&t.push(", ");const s=e.elements[r];switch(this.getType(s)){case"Integer":this.castValueToFloat(s,t);break;case"LiteralInteger":this.castLiteralToFloat(s,t);break;default:this.astGeneric(s,t)}}return t.push(")"),t}memberExpressionXYZ(e,t,s,r){return s?r.push(this.memberExpressionPropertyMarkup(s),", "):r.push("0, "),t?r.push(this.memberExpressionPropertyMarkup(t),", "):r.push("0, "),r.push(this.memberExpressionPropertyMarkup(e)),r}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("building-integer");break;default:this.astGeneric(e,t)}return t.join("")}}}}),rt=e((e,t)=>{let s=null;t.exports={WebGPUContext:class e{static get isSupported(){return"undefined"!=typeof navigator&&!!navigator.gpu}static acquire(){if(s)return s;const t=(async()=>{if(!e.isSupported)throw new Error("WebGPU is not supported on this platform (navigator.gpu is missing)");const r=await navigator.gpu.requestAdapter();if(!r)throw new Error("WebGPU is present (navigator.gpu) but no adapter is available. On headless Chromium there is no adapter; run headed. Use `await GPU.isWebGPUAvailable()` to feature-detect.");const n=await r.requestDevice({requiredLimits:{maxStorageBufferBindingSize:r.limits.maxStorageBufferBindingSize,maxBufferSize:r.limits.maxBufferSize}}),i={adapter:r,device:n,isLost:!1};return n.lost.then(e=>{i.isLost=!0,"destroyed"!==e.reason&&console.error(`gpu.js [webgpu]: device lost: ${e.message}`),s===t&&(s=null)}),n.onuncapturederror=e=>{console.error(`gpu.js [webgpu]: ${e.error.message}`)},i})();return t.catch(()=>{s===t&&(s=null)}),s=t}static destroy(){if(!s)return Promise.resolve();const e=s;return s=null,e.then(({device:e})=>{e.destroy()},()=>{})}}}}),nt=e((e,t)=>{t.exports={WebGPUBufferResult:class e{constructor(e){this.buffer=e.buffer,this.output=e.output,this.componentCount=e.componentCount||1,this.context=e.context,this.kernel=e.kernel,this.type="WebGPUBuffer",this._deleted=!1,this.buffer._refs?this.buffer._refs++:this.buffer._refs=1}toArray(){return this._deleted?Promise.reject(new Error("WebGPUBufferResult has been deleted")):this.kernel.readBufferResult(this)}delete(){this._deleted||(this._deleted=!0,0===--this.buffer._refs&&this.buffer.destroy())}clone(){return new e(this)}}}}),it=e((e,t)=>{const{Kernel:s}=a(),{FunctionBuilder:n}=o(),{WGSLFunctionNode:u}=st(),{WebGPUContext:l}=rt(),{WebGPUBufferResult:h}=nt(),{utils:c}=i(),{Input:p}=r(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0}),f={_pow:"fn _pow(v1 : f32, v2 : f32) -> f32 {\n if (v2 == 0.0) { return 1.0; }\n return pow(v1, v2);\n}",_round:"fn _round(x : f32) -> f32 {\n return floor(x + 0.5);\n}",cbrt:"fn cbrt(x : f32) -> f32 {\n return sign(x) * pow(abs(x), 1.0 / 3.0);\n}",expm1:"fn expm1(x : f32) -> f32 {\n return exp(x) - 1.0;\n}",fround:"fn fround(x : f32) -> f32 {\n return x;\n}",imul:"fn imul(a : f32, b : f32) -> f32 {\n return f32(i32(a) * i32(b));\n}",log10:`fn log10(x : f32) -> f32 {\n return log2(x) * ${1/Math.log2(10)};\n}`,log1p:"fn log1p(x : f32) -> f32 {\n return log(1.0 + x);\n}",clz32:"fn clz32(x : f32) -> f32 {\n return f32(countLeadingZeros(u32(x)));\n}"};t.exports={WebGPUKernel:class extends s{static get isSupported(){return l.isSupported}static get isAsync(){return!0}static isContextMatch(e){return Boolean(e&&"function"==typeof e.createShaderModule&&"function"==typeof e.createComputePipeline)}static getFeatures(){return d}static get features(){return d}static get mode(){return"webgpu"}static getSignature(e,t){return"webgpu"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static nativeFunctionArguments(){throw new Error("WebGPU backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebGPU backend does not yet support native functions")}static combineKernels(){throw new Error("WebGPU backend does not yet support combineKernels; chain kernels with `await` and pipeline mode instead")}constructor(e,t){if(super(e,t),t){if("unsigned"===t.precision&&!t.graphical)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(t.subKernels)throw new Error("WebGPU backend does not yet support createKernelMap")}this.mergeSettings(e.settings||t),(null===this.precision||this.graphical)&&(this.precision="single"),this.asyncMode=!0,this.threadDim=null,this.componentCount=1,this.compiledSource=null,this.translatedBody=null,this.translatedFunctions=null,this.paramsLayout=null,this._buildPromise=null,this._device=null,this.computePipeline=null,this.bindGroupLayout=null,this.bindGroup=null,this.bindGroupDirty=!0,this.paramsBuffer=null,this.paramsMirror=null,this.outputBuffer=null,this.argumentBuffers=null,this.constantBuffers=null,this.stagingPool=[],this._canvasContext=null,this._blitPipeline=null,this._blitParamsBuffer=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built){if(!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");if(t.length!==this.output.length)throw new Error("WebGPU backend does not yet support changing the output rank of a built kernel; the workgroup shape is fixed at build")}return this.output=t,this}toString(){throw new Error("WebGPU backend does not yet support toString")}validateSettings(e){if(this.graphical){if(!this.output||2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");if(this.pipeline)throw new Error("graphical mode and pipeline mode are mutually exclusive");if(!this.canvas)throw new Error("graphical mode requires a canvas (none could be created; pass one in settings)")}if("unsigned"===this.precision)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(this.precision="single",this.subKernels&&this.subKernels.length>0)throw new Error("WebGPU backend does not yet support createKernelMap");if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=Array.from(c.getDimensions(e[0]));else{if("WebGPUBuffer"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(e[0].output)}}this.checkOutput()}setupArguments(e){super.setupArguments(e);for(let e=0;e,`);for(let e=0;e params : Params;");for(let t=0;t user_${e[t].name} : array;`);const i=1+e.length;r.push(`@group(0) @binding(${i}) var result : array;`),this.graphical&&r.push("fn kernelColor(index : i32, r : f32, g : f32, b : f32, a : f32) {\n result[index * 4] = r;\n result[index * 4 + 1] = g;\n result[index * 4 + 2] = b;\n result[index * 4 + 3] = a;\n}");for(let e=0;e constants_${s[e].name} : array;`);r.push("var threadGid : vec3;"),null!==this.paramsLayout.randomSeedOffset&&r.push("var pcgState : u32;\nfn pcg_random() -> f32 {\n pcgState = pcgState * 747796405u + 2891336453u;\n let word = ((pcgState >> ((pcgState >> 28u) + 4u)) ^ pcgState) * 277803737u;\n let mixed = (word >> 22u) ^ word;\n return f32(mixed >> 8u) / 16777216.0;\n}");const a=`${this.translatedFunctions}\n${this.translatedBody}`;/\bLOOP_MAX\b/.test(a)&&r.push(`const LOOP_MAX : i32 = ${parseInt(this.loopMaxIterations,10)||1e3};`);for(const e in f)new RegExp(`\\b${e}\\(`).test(a)&&r.push(f[e]);for(let t=0;t f32 {\n return user_${s}[u32(x + i32(params.user_${s}_dims.x) * (y + i32(params.user_${s}_dims.y) * z))];\n}`)}for(let e=0;e f32 {\n return constants_${t.name}[u32(x + ${i[0]} * (y + ${i[1]} * z))];\n}`)}this.translatedFunctions&&r.push(this.translatedFunctions);const o=1===this.output.length?[64,1,1]:[8,8,1];return this.workgroupSize=o,1===this.output.length?r.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n let flat_index : u32 = gid.x + gid.y * params.dispatchWidth;\n threadGid = vec3(flat_index, 0u, 0u);\n if (flat_index >= params.outputX) { return; }\n let data_index : i32 = i32(flat_index);\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`):r.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n threadGid = gid;\n if (gid.x >= params.outputX || gid.y >= params.outputY || gid.z >= params.outputZ) { return; }\n let data_index : i32 = i32(gid.x + params.outputX * (gid.y + params.outputY * gid.z));\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`),r.join("\n")}constantDimensions(e){const t=e instanceof p?Array.from(e.size):Array.from(c.getDimensions(e));for(;t.length<3;)t.push(1);return t}async _buildAsync(){const e=await l.acquire();this.context=e;const t=this._device=e.device,s=t.createShaderModule({code:this.compiledSource}),r=(await s.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(r.length>0)throw new Error("Error compiling WGSL compute shader:\n"+r.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n")+`\n--- generated WGSL ---\n${this.compiledSource}`);const{arrayArgs:n,bufferConstants:i,byteLength:a}=this.paramsLayout,o=[{binding:0,visibility:4,buffer:{type:"uniform"}}];for(let e=0;ei&&(n[1]=Math.ceil(n[0]/i),n[0]=Math.ceil(n[0]/n[1])),a=n[0]*t);for(let e=0;e<3;e++)if(n[e]>i)throw new Error(`output dimension ${e} needs ${n[e]} workgroups, over this device's limit of ${i}`);return{groups:n,dispatchWidth:a}}async _buildBlitPipeline(e){if(this.canvas.width=this.output[0],this.canvas.height=this.output[1],this._canvasContext=this.canvas.getContext("webgpu"),!this._canvasContext)throw new Error("could not get a webgpu context from the canvas");const t=navigator.gpu.getPreferredCanvasFormat();this._canvasContext.configure({device:e,format:t,alphaMode:"premultiplied"});const s=e.createShaderModule({code:"struct BlitParams { width : u32, height : u32, pad0 : u32, pad1 : u32 }\n@group(0) @binding(0) var blit : BlitParams;\n@group(0) @binding(1) var pixels : array;\n@vertex fn vs(@builtin(vertex_index) vi : u32) -> @builtin(position) vec4 {\n var pos = array, 3>(vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));\n return vec4(pos[vi], 0.0, 1.0);\n}\n@fragment fn fs(@builtin(position) pos : vec4) -> @location(0) vec4 {\n let x = u32(pos.x);\n let y = u32(pos.y);\n let row = blit.height - 1u - y;\n let i = (row * blit.width + x) * 4u;\n let a = pixels[i + 3u];\n return vec4(pixels[i] * a, pixels[i + 1u] * a, pixels[i + 2u] * a, a);\n}"}),r=(await s.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(r.length>0)throw new Error("Error compiling the graphical blit shader:\n"+r.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n"));this._blitBindGroupLayout=e.createBindGroupLayout({entries:[{binding:0,visibility:2,buffer:{type:"uniform"}},{binding:1,visibility:2,buffer:{type:"read-only-storage"}}]}),this._blitPipeline=e.createRenderPipeline({layout:e.createPipelineLayout({bindGroupLayouts:[this._blitBindGroupLayout]}),vertex:{module:s,entryPoint:"vs"},fragment:{module:s,entryPoint:"fs",targets:[{format:t}]},primitive:{topology:"triangle-list"}}),this._blitParamsBuffer=e.createBuffer({size:16,usage:72})}_ensureOutputBuffer(){const[e,t,s]=this.threadDim,r=e*t*s*4*this.componentCount;this.immutable&&this.pipeline&&this.outputBuffer&&(0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this.outputBuffer=null,this.bindGroupDirty=!0),this.outputBuffer&&this.outputBuffer.size>=r||(this.outputBuffer&&0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this._checkBufferSize(r,`output [${this.output.join(", ")}]`),this.outputBuffer=this._device.createBuffer({size:r,usage:132}),this.outputBuffer._refs=1,this.bindGroupDirty=!0)}_checkBufferSize(e,t){const s=this._device.limits,r=Math.min(s.maxStorageBufferBindingSize,s.maxBufferSize);if(e>r)throw new Error(`WebGPU backend: ${t} needs ${e} bytes but this device allows ${r} per storage buffer (maxStorageBufferBindingSize/maxBufferSize); reduce the output or split the work across kernels`)}_snapshotArguments(e){const t=new Array(e.length);for(let s=0;sthis._runInternal(e))}_runInternal(e){if(this.context&&this.context.isLost)throw new Error("WebGPU device was lost; call kernel.destroy() (or gpu.destroy()) and run again to rebuild on a fresh device");const t=this._device,s=t.queue,{arrayArgs:r,scalarArgs:n,bufferConstants:i}=this.paramsLayout,a=this.threadDim=Array.from(this.output);for(;a.length<3;)a.push(1);if(this._ensureOutputBuffer(),null!==this.paramsLayout.randomSeedOffset){const e=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0;this.paramsU32[this.paramsLayout.randomSeedOffset/4]=e}this.paramsU32[0]=a[0],this.paramsU32[1]=a[1],this.paramsU32[2]=a[2],this.paramsU32[3]=this._computeDispatch(a).dispatchWidth;for(let n=0;n{const e=new Float32Array(p.buffer.getMappedRange(0,u).slice(0));return p.buffer.unmap(),this._releaseStaging(p),this._shapeOutput(e,d,this.componentCount)},e=>{throw this._releaseStaging(p),e})}_acquireStaging(e){for(let t=0;t=e)return s.busy=!0,s}const t={buffer:this._device.createBuffer({size:e,usage:9}),size:e,busy:!0,pooled:this.stagingPool.length<3};return t.pooled&&this.stagingPool.push(t),t}_releaseStaging(e){e.pooled?e.busy=!1:e.buffer.destroy()}_shapeOutput(e,t,s){const[r,n,i]=[t[0],t[1]||1,t[2]||1];if(1===s)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,r);case 2:return c.erectMemoryOptimized2DFloat(e,r,n);default:return c.erectMemoryOptimized3DFloat(e,r,n,i)}const a=s,o=t=>{const s=new Array(r);for(let n=0;n{const t=new Float32Array(i.buffer.getMappedRange(0,n).slice(0));return i.buffer.unmap(),this._releaseStaging(i),this._shapeOutput(t,s,e.componentCount)},e=>{throw this._releaseStaging(i),e})}getPixels(e){if(!this.graphical)return Promise.reject(new Error("getPixels only works on a graphical kernel"));if(!this.outputBuffer)return Promise.reject(new Error("run the kernel before reading its pixels"));const[t,s]=this.output,r=t*s*4*4,n=this._acquireStaging(r),i=this._device.createCommandEncoder();return i.copyBufferToBuffer(this.outputBuffer,0,n.buffer,0,r),this._device.queue.submit([i.finish()]),n.buffer.mapAsync(1,0,r).then(()=>{const i=new Float32Array(n.buffer.getMappedRange(0,r).slice(0));n.buffer.unmap(),this._releaseStaging(n);const a=new Uint8ClampedArray(t*s*4);for(let r=0;r{throw this._releaseStaging(n),e})}destroy(e){if(this._blitParamsBuffer&&(this._blitParamsBuffer.destroy(),this._blitParamsBuffer=null),this._canvasContext&&(this._canvasContext.unconfigure(),this._canvasContext=null),this._blitPipeline=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null,this.paramsBuffer&&(this.paramsBuffer.destroy(),this.paramsBuffer=null),this.paramsLayout)for(let e=0;e{const s={i32:127,i64:126,f32:125,f64:124,v128:123},r=new DataView(new ArrayBuffer(16));function n(e,t){let s=e>>>0;do{let e=127&s;s>>>=7,0!==s&&(e|=128),t.push(e)}while(0!==s)}function i(e,t){let s=0|e;for(;;){const e=127&s;if(s>>=7,0===s&&!(64&e)||-1===s&&64&e)return void t.push(e);t.push(128|e)}}function a(e,t,s){let r=e>>>0;for(let e=0;e<4;e++)t[s+e]=127&r|128,r>>>=7;t[s+4]=127&r}function o(e,t){const s=[];for(let t=0;t65535&&t++,r<128?s.push(r):r<2048?s.push(192|r>>6,128|63&r):r<65536?s.push(224|r>>12,128|r>>6&63,128|63&r):s.push(240|r>>18,128|r>>12&63,128|r>>6&63,128|63&r)}n(s.length,t);for(let e=0;e3)throw new Error(`WasmModuleBuilder: lane index ${t} out of range for 4-lane shape`);return this.bytes.push(253,e,t),this}_push(e){for(let t=0;t${t.join(",")}`;if(s in this.typeIndexByKey)return this.typeIndexByKey[s];const r=this.types.length;return this.types.push({params:e,results:t}),this.typeIndexByKey[s]=r,r}addMemoryImport(e,t,s=!1){if(s&&null==t)throw new Error("WasmModuleBuilder: shared memory import requires a maximum");return this.memoryImport={initial:e,maximum:t,shared:s},this}addFuncImport(e,t,s,r="env"){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);const n=this.funcImports.length;return this.funcImports.push({name:e,module:r,typeIndex:this._typeIndex(t,s)}),this.funcImportIndexByName[e]=n,n}addGlobal(e,t,s){return u(e),this.globals.push({type:e,mutable:t,initialValue:s}),this.globals.length-1}addFunction(e,{params:t=[],results:s=[],locals:r=[]}={}){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);t.forEach(u),s.forEach(u),r.forEach(u);const n=new h(this,e,t,s,r);return this.functionIndexByName[e]=this.functions.length,this.functions.push({name:e,emitter:n,typeIndex:this._typeIndex(t,s)}),n}exportFunction(e,t=e){return this.exports.push({name:e,exportName:t}),this}_resolveFuncIndex(e){if(e in this.funcImportIndexByName)return this.funcImportIndexByName[e];if(e in this.functionIndexByName)return this.funcImports.length+this.functionIndexByName[e];throw new Error(`WasmModuleBuilder: call target "${e}" is not an import or a defined function`)}_section(e,t,s){s.push(e),n(t.length,s);for(let e=0;e0){const t=[];n(this.types.length,t);for(const{params:e,results:s}of this.types){t.push(96),n(e.length,t);for(const s of e)t.push(u(s));n(s.length,t);for(const e of s)t.push(u(e))}this._section(1,t,e)}if(null!==this.memoryImport||this.funcImports.length>0){const t=[];if(n((null!==this.memoryImport?1:0)+this.funcImports.length,t),null!==this.memoryImport){const{initial:e,maximum:s,shared:r}=this.memoryImport;o("env",t),o("memory",t),t.push(2);const i=null!=s;t.push(r?3:i?1:0),n(e,t),i&&n(s,t)}for(const{name:e,module:s,typeIndex:r}of this.funcImports)o(s,t),o(e,t),t.push(0),n(r,t);this._section(2,t,e)}if(this.functions.length>0){const t=[];n(this.functions.length,t);for(const{typeIndex:e}of this.functions)n(e,t);this._section(3,t,e)}if(this.globals.length>0){const t=[];n(this.globals.length,t);for(const{type:e,mutable:s,initialValue:n}of this.globals){if(t.push(u(e),s?1:0),"i32"===e)t.push(65),i(n,t);else if("f32"===e){t.push(67),r.setFloat32(0,n,!0);for(let e=0;e<4;e++)t.push(r.getUint8(e))}else{if("v128"!==e)throw new Error(`WasmModuleBuilder: no initializer encoding for global type "${e}"`);t.push(253,12);for(let e=0;e<16;e++)t.push(0)}t.push(11)}this._section(6,t,e)}if(this.exports.length>0){const t=[];n(this.exports.length,t);for(const{name:e,exportName:s}of this.exports)o(s,t),t.push(0),n(this._resolveFuncIndex(e),t);this._section(7,t,e)}if(this.functions.length>0){const t=[];n(this.functions.length,t);for(const{emitter:e}of this.functions){const s=e.bytes.slice();for(const{at:t,name:r}of e.callFixups)a(this._resolveFuncIndex(r),s,t);const r=[],i=[];for(const t of e.locals){const e=u(t);i.length>0&&i[i.length-1].type===e?i[i.length-1].count++:i.push({type:e,count:1})}n(i.length,r);for(const{type:e,count:t}of i)n(t,r),r.push(e);for(let e=0;e{const{utils:s}=i(),{FunctionNode:r}=l(),{WasmFunctionEmitter:n}=at();var a=class{constructor(){this.localCount=0}addLocal(){return this.localCount++}};for(const e of Object.getOwnPropertyNames(n.prototype))"constructor"!==e&&"addLocal"!==e&&"function"==typeof n.prototype[e]&&(a.prototype[e]=function(){return this});const o={sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,sinh:1,cosh:1,tanh:1,asinh:1,acosh:1,atanh:1,exp:1,expm1:1,log:1,log2:1,log10:1,log1p:1,cbrt:1,pow:2,sign:1},u={abs:"f32Abs",floor:"f32Floor",ceil:"f32Ceil",sqrt:"f32Sqrt",trunc:"f32Trunc"},h={"+":"f32Add","-":"f32Sub","*":"f32Mul"},c={"+":"i32Add","-":"i32Sub","*":"i32Mul"},p={"==":"f32Eq","===":"f32Eq","!=":"f32Ne","!==":"f32Ne","<":"f32Lt",">":"f32Gt","<=":"f32Le",">=":"f32Ge"},d={"==":"i32Eq","===":"i32Eq","!=":"i32Ne","!==":"i32Ne","<":"i32LtS",">":"i32GtS","<=":"i32LeS",">=":"i32GeS"},f={"&":"i32And","|":"i32Or","^":"i32Xor","<<":"i32Shl",">>":"i32ShrS",">>>":"i32ShrU"},m={"+":"f32x4Add","-":"f32x4Sub","*":"f32x4Mul"},g={"+":"i32x4Add","-":"i32x4Sub","*":"i32x4Mul"},y={"==":"f32x4Eq","===":"f32x4Eq","!=":"f32x4Ne","!==":"f32x4Ne","<":"f32x4Lt",">":"f32x4Gt","<=":"f32x4Le",">=":"f32x4Ge"},x={"==":"i32x4Eq","===":"i32x4Eq","!=":"i32x4Ne","!==":"i32x4Ne","<":"i32x4LtS",">":"i32x4GtS","<=":"i32x4LeS",">=":"i32x4GeS"},b={"<<":"i32x4Shl",">>":"i32x4ShrS",">>>":"i32x4ShrU"},v={abs:"f32x4Abs",floor:"f32x4Floor",ceil:"f32x4Ceil",sqrt:"f32x4Sqrt",trunc:"f32x4Trunc"};function S(e){switch(e){case"Number":case"Float":case"LiteralInteger":return"f32";case"Integer":case"Boolean":return"i32";default:throw new Error(`WebAssembly backend does not yet support ${e} arguments to helper functions`)}}t.exports={WebAssemblyFunctionNode:class extends r{constructor(e,t){super(e,t),this.assembler=null,this.em=null,this.locals=null,this.depth=0,this.loopStack=null,this.usedMathImports=new Set,this.usesRandom=!1,this.readsThread=!1,this.taintedLocals=null,this.uniformity=[],this._analysisDone=!1,this._analysisPass=!1,this.vec=!1,this.vMaskDepth=0,this.vCur=-1,this.vRetMask=-1,this.vTerminated=!1,this.vInfo=null,this._vBaseX=-1}mangleFunctionName(e){return`fn_${s.sanitizeName(e)}`}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}toString(){return this._analysisDone||(this._analysisDone=!0,this._analysisPass=!0,this.walkFunction(new a),this._analysisPass=!1),""}emitFunction(e){this.assembler=e;const{module:t}=e;let s;if(this.isRootKernel)s=t.addFunction("kernel",{params:[],results:[]});else{const e=this.argumentTypes.map(e=>S("LiteralInteger"===e?"Number":e)),r=[];if(this.returnType)switch(this.returnType){case"Integer":case"Boolean":r.push("i32");break;case"Number":case"Float":case"LiteralInteger":r.push("f32");break;default:throw new Error(`WebAssembly backend does not yet support helper functions returning ${this.returnType}`)}s=t.addFunction(this.mangleFunctionName(this.name),{params:e,results:r})}return this.walkFunction(s),!this.isRootKernel&&this.returnType&&s.unreachable(),s}walkFunction(e){this.em=e,this.locals=new Map,this.depth=0,this.loopStack=[],this.taintedLocals=new Set;const t=this.getJsAST();if(this.isRootKernel)for(const s of this.collectAssignedArgumentNames(t)){const t=this.argumentNames.indexOf(s),r=this.argumentTypes[t];if("Number"!==r&&"Float"!==r&&"Integer"!==r&&"Boolean"!==r)continue;const n=this.assembler?this.assembler.layout.scalars[s]:null,i=n?n.offset:0,a="Integer"===r||"Boolean"===r?"i32":"f32",o=e.addLocal(a);e.i32Const(0),"i32"===a?e.i32Load(i):e.f32Load(i),e.localSet(o),this.locals.set(s,{kind:"scalar",index:o,wtype:a,gtype:r})}if(!this.isRootKernel){for(let e=0;e{if(r&&"object"==typeof r){if(Array.isArray(r))return r.forEach(s);if("FunctionDeclaration"!==r.type||r===e){"AssignmentExpression"===r.type&&"Identifier"===r.left.type&&-1!==this.argumentNames.indexOf(r.left.name)&&t.add(r.left.name),"UpdateExpression"===r.type&&"Identifier"===r.argument.type&&-1!==this.argumentNames.indexOf(r.argument.name)&&t.add(r.argument.name);for(const e in r){if("loc"===e||"start"===e||"end"===e||"parent"===e)continue;const t=r[e];t&&"object"==typeof t&&s(t)}}}};return s(e.body),t}enterBlock(e){this.em.block(e),this.depth++}enterLoop(e){this.em.loop(e),this.depth++}enterIf(e){this.em.if_(e),this.depth++}exit(){this.em.end(),this.depth--}brTo(e){this.em.br(this.depth-e)}brIfTo(e){this.em.brIf(this.depth-e)}get loopMax(){return parseInt(this.loopMaxIterations,10)||1e3}coerce(e,t){if(e===t)return t;if("void"===e)throw new Error("cannot use a void expression as a value");switch(t){case"f32":return this.em.f32ConvertI32S(),"f32";case"i32":return"f32"===e&&this.em.i32TruncSatF32S(),"i32";case"bool":return"f32"===e?this.em.f32Const(0).f32Ne():this.em.i32Eqz().i32Eqz(),"bool";default:throw new Error(`unknown wasm value category ${t}`)}}castLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castLiteralToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}castValueToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castValueToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}emitByType(e,t){const s=this.getType(e);return"f32"===t?"Integer"===s?this.castValueToFloat(e):"LiteralInteger"===s?this.castLiteralToFloat(e):(this.coerce(this.expression(e),"f32"),"f32"):"Number"===s||"Float"===s?this.castValueToInteger(e):"LiteralInteger"===s?this.castLiteralToInteger(e):(this.coerce(this.expression(e),"i32"),"i32")}emitCondition(e){const t=this.expression(e);if("bool"!==t)if("i32"!==t){if("f32"!==t)throw this.astErrorOutput("cannot use a void expression as a condition",e);this.em.f32Const(0).f32Ne()}else this.em.i32Eqz().i32Eqz()}statement(e){switch(e.type){case"VariableDeclaration":return this.stmtVariableDeclaration(e);case"ExpressionStatement":return this.statementExpression(e.expression);case"ReturnStatement":return this.stmtReturn(e);case"IfStatement":return this.stmtIf(e);case"ForStatement":return this.stmtFor(e);case"WhileStatement":return this.stmtWhile(e);case"DoWhileStatement":return this.stmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.castValueToFloat(n));else switch(i.valueType=u,u){case"Number":case"Float":this.setScalarLocal(o,"f32",u,()=>{"LiteralInteger"===a?this.castLiteralToFloat(n):"Integer"===a?this.castValueToFloat(n):this.coerce(this.expression(n),"f32")});break;case"Integer":this.setScalarLocal(o,"i32","Integer",()=>{"LiteralInteger"===a?this.castLiteralToInteger(n):"Number"===a||"Float"===a?this.castValueToInteger(n):this.coerce(this.expression(n),"i32")});break;case"Boolean":this.setScalarLocal(o,"i32","Boolean",()=>this.emitCondition(n));break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${u}`,e)}this.isThreadDependent(n)&&this.taintedLocals.add(o)}}setScalarLocal(e,t,s,r){let n=this.locals.get(e);n&&"scalar"===n.kind&&n.wtype===t?n.gtype=s:(n={kind:"scalar",index:this.em.addLocal(t),wtype:t,gtype:s},this.locals.set(e,n)),r(),this.em.localSet(n.index)}declareVecLocal(e,t,s,r,n){const i=parseInt(t.substring(6),10);r.valueType=t;let a=this.locals.get(e);if(!a||"vec"!==a.kind||a.n!==i){const s=[];for(let e=0;ethis.em.localSet(s.index);else{if(s||!this.isRootKernel||-1===this.argumentNames.indexOf(t))throw this.astErrorOutput(`cannot assign to "${t}"`,e);{const s=this.argumentTypes[this.argumentNames.indexOf(t)],i=this.assembler?this.assembler.layout.scalars[t]:null;if(this.assembler&&!i)throw this.astErrorOutput(`WebAssembly backend does not yet support assigning to the array argument "${t}"`,e);const a=i?i.offset:0;r="Integer"===s||"Boolean"===s?"i32":"f32",this.em.i32Const(0),n=()=>"i32"===r?this.em.i32Store(a):this.em.f32Store(a)}}if("="===e.operator){const t=this.getType(e.left),s=this.getType(e.right);"Integer"!==t&&"Integer"===s?(this.castValueToFloat(e.right),this.coerce("f32",r)):"Integer"!==t&&"LiteralInteger"===s?(this.castLiteralToFloat(e.right),this.coerce("f32",r)):"Integer"===t&&"LiteralInteger"===s?(this.castLiteralToInteger(e.right),this.coerce("i32",r)):"Integer"!==t||"Number"!==s&&"Float"!==s?this.coerce(this.expression(e.right),r):(this.castValueToInteger(e.right),this.coerce("i32",r))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.coerce(this.exprBinary(t),r)}n(),(this.isThreadDependent(e.right)||"="!==e.operator&&this.taintedLocals.has(t))&&this.taintedLocals.add(t)}emitUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const s=this.locals.get(e.argument.name);if(!s||"scalar"!==s.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const r="i32"===s.wtype,n=()=>r?this.em.i32Const(1):this.em.f32Const(1),i="++"===e.operator?r?"i32Add":"f32Add":r?"i32Sub":"f32Sub";return t?(this.em.localGet(s.index),n(),this.em[i]().localSet(s.index),"void"):(e.prefix?(this.em.localGet(s.index),n(),this.em[i]().localTee(s.index)):(this.em.localGet(s.index).localGet(s.index),n(),this.em[i]().localSet(s.index)),s.wtype)}stmtReturn(e){if(!e.argument){if(this.isRootKernel)return void this.em.return_();throw this.astErrorOutput("Unexpected return statement",e)}this.pushState("skip-literal-correction");const t=this.getType(e.argument);if(this.popState("skip-literal-correction"),this.returnType||(this.returnType="LiteralInteger"===t||"Integer"===t?"Number":t),this.isRootKernel)return this.stmtRootReturn(e,t);if(this.isSubKernel)throw this.astErrorOutput("WebAssembly backend does not yet support createKernelMap",e);switch(this.returnType){case"LiteralInteger":case"Number":case"Float":"Integer"===t?this.castValueToFloat(e.argument):"LiteralInteger"===t?this.castLiteralToFloat(e.argument):this.coerce(this.expression(e.argument),"f32");break;case"Integer":"Float"===t||"Number"===t?this.castValueToInteger(e.argument):"LiteralInteger"===t?this.castLiteralToInteger(e.argument):this.coerce(this.expression(e.argument),"i32");break;case"Boolean":this.emitCondition(e.argument);break;default:throw this.astErrorOutput(`unhandled return type ${this.returnType}`,e)}this.em.return_()}stmtRootReturn(e,t){const s=this.assembler?this.assembler.globals:{dataIndex:0},r=this.assembler?this.assembler.layout.outputOffset:0;switch(this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const t=parseInt(this.returnType.substring(6),10),n=e.argument;if("ArrayExpression"===n.type){if(n.elements.length!==t)throw this.astErrorOutput(`expected ${t} array elements to match return type ${this.returnType}`,e);for(let e=0;e1&&(t=!1);for(let e=0;e{if(e===a.length)return o&&this.emitSwitchConsequent(o),!1;const{tests:t,consequent:s}=a[e];for(let e=0;e0&&this.em.i32Or();return this.enterIf(),this.emitSwitchConsequent(s),(e+10&&(s.push({tests:r,consequent:e[n].consequent}),r=[])):t=e[n].consequent;return{groups:s,defaultConsequent:t}}collectSwitchCaseStatements(e){const t=[];for(let s=0;s{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(s);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&s(e[t]))return!0;return!1};for(let e=0;e{const s=this.getType(t);switch(r){case"Number":case"Float":"Integer"===s?this.castValueToFloat(t):"LiteralInteger"===s?this.castLiteralToFloat(t):this.coerce(this.expression(t),"f32");break;case"Integer":"Number"===s||"Float"===s?this.castValueToInteger(t):"LiteralInteger"===s?this.castLiteralToInteger(t):this.coerce(this.expression(t),"i32");break;case"Boolean":this.emitCondition(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${r}`,e)}};return this.emitCondition(e.test),this.enterIf(n),i(e.consequent),this.em.else_(),i(e.alternate),this.exit(),"Boolean"===r?"bool":n}exprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const s=this.isAstMathFunction(e);if(t=s||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);if(this.calledFunctions.indexOf(t)<0&&this.calledFunctions.push(t),this.onFunctionCall&&this.onFunctionCall(this.name,t,e.arguments),s)return this.emitMathCall(t,e);const r=this.getType(e),n=this.lookupFunctionArgumentTypes(t)||[];for(let s=0;s{switch(this.getType(e)){case"Integer":this.castValueToFloat(e);break;case"LiteralInteger":this.castLiteralToFloat(e);break;default:this.coerce(this.expression(e),"f32")}},r=u[e];if(r)return s(t.arguments[0]),this.em[r](),"f32";switch(e){case"round":return s(t.arguments[0]),this.em.f32Const(.5).f32Add().f32Floor(),"f32";case"fround":return s(t.arguments[0]),"f32";case"min":case"max":{const r="min"===e?"f32Min":"f32Max";s(t.arguments[0]);for(let e=1;e0&&this.emitClampScalarIndex(a.dims[0]*a.dims[1]*a.dims[2]-1),this.em.i32Const(2).i32Shl(),this.em.f32Load(a.offset),"f32"}emitClampScalarIndex(e){const t=this.em.addLocal("i32");this.em.localSet(t),this.em.localGet(t).i32Const(0).localGet(t).i32Const(0).i32GeS().select(),this.em.localSet(t),this.em.localGet(t).i32Const(e).localGet(t).i32Const(e).i32LeS().select()}emitVecIndex(e,t){if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return this.em.localGet(e.indices[t.value]),"f32"}const s=this.em.addLocal("i32");this.emitIndex(t),this.em.localSet(s),this.em.localGet(e.indices[0]);for(let t=1;t{if(!e||"object"!=typeof e)return!1;switch(e.type){case"Literal":case"ThisExpression":return!1;case"Identifier":return t.has(e.name);case"MemberExpression":return e.computed||"MemberExpression"!==e.object.type||e.object.computed||!e.object.property||"thread"!==e.object.property.name?e.computed?a(e.object)||a(e.property):a(e.object):"x"===e.property.name;case"BinaryExpression":case"LogicalExpression":return a(e.left)||a(e.right);case"UnaryExpression":case"UpdateExpression":return a(e.argument);case"ConditionalExpression":return a(e.test)||a(e.consequent)||a(e.alternate);case"CallExpression":return!i.isAstMathFunction(e)||("random"===e.callee.property.name||e.arguments.some(a));case"SequenceExpression":return e.expressions.some(a);case"ArrayExpression":return e.elements.some(a);case"AssignmentExpression":return a(e.right)||"Identifier"===e.left.type&&t.has(e.left.name);default:return!0}},o=e=>{e&&!t.has(e)&&(t.add(e),n=!0)},u=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>u(e,t));switch(e.type){case"UpdateExpression":return"Identifier"===e.argument.type&&(-1!==i.argumentNames.indexOf(e.argument.name)&&(s.has(e.argument.name)||(s.add(e.argument.name),n=!0),o(e.argument.name)),t&&o(e.argument.name)),u(e.argument,t);case"AssignmentExpression":return"Identifier"===e.left.type&&(-1!==i.argumentNames.indexOf(e.left.name)&&(s.has(e.left.name)||(s.add(e.left.name),n=!0),o(e.left.name)),t&&o(e.left.name)),u(e.left,t),u(e.right,t);case"ConditionalExpression":{u(e.test,t);const s=t||a(e.test);return u(e.consequent,s),u(e.alternate,s)}case"LogicalExpression":return u(e.left,t),u(e.right,!0);default:for(const s in e){if("loc"===s||"start"===s||"end"===s||"parent"===s)continue;const r=e[s];r&&"object"==typeof r&&u(r,t)}}}},l=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>l(e,t));switch(e.type){case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.push(e.id.name);break;case"AssignmentExpression":"Identifier"===e.left.type&&t.push(e.left.name);break;case"UpdateExpression":"Identifier"===e.argument.type&&t.push(e.argument.name);break;case"FunctionDeclaration":return}for(const s in e){if("loc"===s||"start"===s||"end"===s||"parent"===s)continue;const r=e[s];r&&"object"==typeof r&&l(r,t)}}},h=(e,t)=>{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>h(e,t));switch(e.type){case"BreakStatement":case"ContinueStatement":return t;case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return!1;case"IfStatement":{const s=t||a(e.test);return!!h(e.consequent,s)||!!e.alternate&&h(e.alternate,s)}case"ConditionalExpression":{const s=t||a(e.test);return h(e.consequent,s)||h(e.alternate,s)}case"SwitchStatement":{const s=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));return e.cases.some(e=>e.consequent.some(e=>"BreakStatement"!==e.type&&h(e,s)))}default:for(const s in e){if("loc"===s||"start"===s||"end"===s||"parent"===s)continue;const r=e[s];if(r&&"object"==typeof r&&h(r,t))return!0}return!1}},c=(e,r)=>{switch(e.type){case"AssignmentExpression":if("Identifier"===e.left.type){const u=e.left.name;-1!==i.argumentNames.indexOf(u)&&(s.has(u)||(s.add(u),n=!0),o(u)),(r||a(e.right)||"="!==e.operator&&t.has(u))&&o(u)}return u(e.right,r);case"UpdateExpression":if("Identifier"===e.argument.type){const t=e.argument.name;-1!==i.argumentNames.indexOf(t)&&(s.has(t)||(s.add(t),n=!0),o(t)),r&&o(t)}return;case"SequenceExpression":return e.expressions.forEach(e=>c(e,r));default:return u(e,r)}},p=(e,t)=>{if(e)switch(e.type){case"VariableDeclaration":for(const s of e.declarations)s.init&&((t||a(s.init))&&o(s.id.name),u(s.init,t));return;case"ExpressionStatement":return c(e.expression,t);case"ReturnStatement":return t&&(r=!0),void(e.argument&&u(e.argument,t));case"IfStatement":{u(e.test,t);const s=t||a(e.test);return p(e.consequent,s),void(e.alternate&&p(e.alternate,s))}case"ForStatement":case"WhileStatement":case"DoWhileStatement":{const s=t||!!e.test&&a(e.test)||h(e.body,!1);if(s){const t=[];e.init&&l(e.init,t),l(e.body,t),e.update&&l(e.update,t),t.forEach(o)}return e.init&&("VariableDeclaration"===e.init.type?p(e.init,t):c(e.init,t)),p(e.body,s),e.update&&c(e.update,s),void(e.test&&u(e.test,s))}case"SwitchStatement":{const s=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));for(const t of e.cases)for(const e of t.consequent)p(e,s);return}case"BlockStatement":return e.body.forEach(e=>p(e,t));default:return}};for(;n;)n=!1,p(e.body,!1);return{varying:t,varyingReturn:r,assignedArgs:s,exprVarying:a,hasVaryingExit:h}}vZero(){return this.em.v128ConstI32x4(0,0,0,0),this}vInnermostVaryingLoop(){const e=this.vLoopStack[this.vLoopStack.length-1];return e&&e.varying?e:null}vRecomputeCur(e){const t=this.em;t.localGet(e),-1!==this.vRetMask&&t.localGet(this.vRetMask).v128Andnot();const s=this.vInnermostVaryingLoop();s&&(-1!==s.vBrk&&t.localGet(s.vBrk).v128Andnot(),-1!==s.vCnt&&t.localGet(s.vCnt).v128Andnot()),t.localSet(this.vCur)}vLoopBodyExits(e){let t=!1,s=!1;const r=e=>{if(!(!e||"object"!=typeof e||t&&s)){if(Array.isArray(e))return e.forEach(r);switch(e.type){case"BreakStatement":return void(t=!0);case"ContinueStatement":return void(s=!0);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return;case"SwitchStatement":for(const t of e.cases)for(const e of t.consequent)"BreakStatement"!==e.type&&r(e);return}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const s=e[t];s&&"object"==typeof s&&r(s)}}};return r(e),{hasBreak:t,hasContinue:s}}vSetLocal(e){const t=this.em;this.vMaskDepth>0&&t.localGet(e).localGet(this.vCur).v128Bitselect(),t.localSet(e)}vCoerce(e,t){if(e===t)return t;const s=this.em;switch(e){case"f32":case"i32":case"bool":if("vf32"===t)return this.coerce(e,"f32"),s.f32x4Splat(),t;if("vi32"===t)return this.coerce(e,"i32"),s.i32x4Splat(),t;if("vbool"===t)return this.coerce(e,"i32"),s.i32x4Splat(),this.vZero(),s.i32x4Ne(),t;break;case"vf32":if("vi32"===t)return s.i32x4TruncSatF32x4S(),t;if("vbool"===t)return s.v128ConstF32x4(0,0,0,0).f32x4Ne(),t;break;case"vi32":if("vf32"===t)return s.f32x4ConvertI32x4S(),t;if("vbool"===t)return this.vZero(),s.i32x4Ne(),t;break;case"vbool":if("vi32"===t)return s.v128ConstI32x4(1,1,1,1).v128And(),t;if("vf32"===t)return s.v128ConstI32x4(1,1,1,1).v128And().f32x4ConvertI32x4S(),t}throw new Error(`cannot convert ${e} to ${t}`)}vCastLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastLiteralToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vCastValueToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastValueToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vEmitByType(e,t){const s=this.getType(e);return"vf32"===t?"Integer"===s?this.vCastValueToFloat(e):"LiteralInteger"===s?this.vCastLiteralToFloat(e):(this.vCoerce(this.vexpr(e),"vf32"),"vf32"):"Number"===s||"Float"===s?this.vCastValueToInteger(e):"LiteralInteger"===s?this.vCastLiteralToInteger(e):(this.vCoerce(this.vexpr(e),"vi32"),"vi32")}vexprMask(e){const t=this.vexpr(e);if("vbool"!==t)return"vi32"===t?(this.vZero(),void this.em.i32x4Ne()):void("vf32"!==t?(this.coerce(t,"bool"),this.em.i32x4Splat(),this.vZero(),this.em.i32x4Ne()):this.em.v128ConstF32x4(0,0,0,0).f32x4Ne())}vstatement(e){switch(e.type){case"VariableDeclaration":return this.vstmtVariableDeclaration(e);case"ExpressionStatement":return this.vstatementExpression(e.expression);case"ReturnStatement":return this.vstmtReturn(e);case"IfStatement":return this.vstmtIf(e);case"ForStatement":return this.vstmtFor(e);case"WhileStatement":return this.vstmtWhile(e);case"DoWhileStatement":return this.vstmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.vCastValueToFloat(r));switch(i.valueType=o,o){case"Number":case"Float":this.vSetVaryingScalar(n,"vf32",o,()=>{"LiteralInteger"===a?this.vCastLiteralToFloat(r):"Integer"===a?this.vCastValueToFloat(r):this.vCoerce(this.vexpr(r),"vf32")});break;case"Integer":this.vSetVaryingScalar(n,"vi32","Integer",()=>{"LiteralInteger"===a?this.vCastLiteralToInteger(r):"Number"===a||"Float"===a?this.vCastValueToInteger(r):this.vCoerce(this.vexpr(r),"vi32")});break;case"Boolean":this.vSetVaryingScalar(n,"vi32","Boolean",()=>{this.vexprMask(r),this.em.v128ConstI32x4(1,1,1,1).v128And()});break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${o}`,t)}}vSetVaryingScalar(e,t,s,r){let n=this.locals.get(e);n&&"vscalar"===n.kind&&n.wtype===t?n.gtype=s:(n={kind:"vscalar",index:this.em.addLocal("v128"),wtype:t,gtype:s},this.locals.set(e,n)),r(),this.vSetLocal(n.index)}vEmitArrayElement(e){switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}}vAssign(e){if("Identifier"!==e.left.type)throw this.astErrorOutput(`WebAssembly backend does not yet support assignment to ${e.left.type}`,e);const t=e.left.name,s=this.locals.get(t);if(s&&"scalar"===s.kind)return this.emitAssignment(e);if(!s||"vscalar"!==s.kind)throw this.astErrorOutput(`cannot assign to "${t}"`,e);const r=s.wtype;if("="===e.operator){const t=this.getType(e.left),s=this.getType(e.right);"Integer"!==t&&"Integer"===s?(this.vCastValueToFloat(e.right),this.vCoerce("vf32",r)):"Integer"!==t&&"LiteralInteger"===s?(this.vCastLiteralToFloat(e.right),this.vCoerce("vf32",r)):"Integer"===t&&"LiteralInteger"===s?(this.vCastLiteralToInteger(e.right),this.vCoerce("vi32",r)):"Integer"!==t||"Number"!==s&&"Float"!==s?this.vCoerce(this.vexpr(e.right),r):(this.vCastValueToInteger(e.right),this.vCoerce("vi32",r))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.vCoerce(this.vexprBinary(t),r)}this.vSetLocal(s.index)}vUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const s=this.locals.get(e.argument.name);if(s&&"scalar"===s.kind)return this.emitUpdate(e,t);if(!s||"vscalar"!==s.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const r=this.em,n="vi32"===s.wtype,i=()=>n?r.v128ConstI32x4(1,1,1,1):r.v128ConstF32x4(1,1,1,1),a="++"===e.operator?n?"i32x4Add":"f32x4Add":n?"i32x4Sub":"f32x4Sub";if(t)return r.localGet(s.index),i(),r[a](),this.vSetLocal(s.index),"void";if(e.prefix)r.localGet(s.index),i(),r[a](),this.vSetLocal(s.index),r.localGet(s.index);else{const e=r.addLocal("v128");r.localGet(s.index).localSet(e),r.localGet(s.index),i(),r[a](),this.vSetLocal(s.index),r.localGet(e)}return s.wtype}vstmtIf(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementBody(e.consequent),e.alternate&&(t.else_(),this.vstatementBody(e.alternate)),void this.exit();const s=t.addLocal("v128");this.vexprMask(e.test),t.localSet(s);const r=t.addLocal("v128");t.localGet(this.vCur).localSet(r),t.localGet(r).localGet(s).v128And().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.consequent),this.vMaskDepth--,this.exit(),e.alternate&&(t.localGet(r).localGet(s).v128Andnot().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.alternate),this.vMaskDepth--,this.exit()),this.vRecomputeCur(r)}vstmtReturn(e){const t=this.em;if(!e.argument)return void this.vRetireOrReturn();this.pushState("skip-literal-correction");const s=this.getType(e.argument);switch(this.popState("skip-literal-correction"),this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const s=parseInt(this.returnType.substring(6),10),r=e.argument,n=[];if("ArrayExpression"===r.type){if(r.elements.length!==s)throw this.astErrorOutput(`expected ${s} array elements to match return type ${this.returnType}`,e);for(let e=0;e0?i=this.vCur:-1!==this.vRetMask&&(i=t.addLocal("v128"),t.localGet(this.vRetMask).v128Not().localSet(i));const a=t.addLocal("i32");if(1===n)return t.globalGet(s.dataIndex).i32Const(2).i32Shl().localSet(a),void(-1===i?t.localGet(a).localGet(e[0]).v128Store(r,2):(t.localGet(a),t.localGet(e[0]),t.localGet(a).v128Load(r,2),t.localGet(i).v128Bitselect(),t.v128Store(r,2)));t.globalGet(s.dataIndex).i32Const(n).i32Mul().i32Const(2).i32Shl().localSet(a);for(let s=0;s<4;s++)for(let o=0;oe.test&&this.vInfo.exprVarying(e.test)),i=this.getType(t);if(!n){let n,a;switch(i){case"Float":case"Number":a=!1,n=r.addLocal("f32"),this.coerce(this.expression(t),"f32"),r.localSet(n);break;case"Integer":a=!0,n=r.addLocal("i32"),this.coerce(this.expression(t),"i32"),r.localSet(n);break;default:throw this.astErrorOutput(`Unhandled switch discriminant type "${i}"`,e)}if(1===s.length&&!s[0].test)return void this.vEmitSwitchConsequent(s[0].consequent);const{groups:o,defaultConsequent:u}=this.collectSwitchGroups(s),l=e=>{if(e===o.length)return void(u&&this.vEmitSwitchConsequent(u));const{tests:t,consequent:s}=o[e];for(let e=0;e0&&r.i32Or();this.enterIf(),this.vEmitSwitchConsequent(s),(e+10&&r.v128Or();r.localSet(p),this.vRecomputeCur(h),r.localGet(this.vCur).localGet(p).v128And().localGet(c).v128Andnot().localSet(this.vCur),r.localGet(c).localGet(p).v128Or().localSet(c),r.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(s),this.exit()}l&&(this.vRecomputeCur(h),r.localGet(this.vCur).localGet(c).v128Andnot().localSet(this.vCur),r.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(l),this.exit()),this.vMaskDepth--,this.vRecomputeCur(h)}vEmitSwitchTest(e,t){const s=this.getType(e);t?"Number"===s||"Float"===s?this.vCastValueToInteger(e):"LiteralInteger"===s?this.vCastLiteralToInteger(e):this.vCoerce(this.vexpr(e),"vi32"):"LiteralInteger"===s?this.vCastLiteralToFloat(e):"Integer"===s?this.vCastValueToFloat(e):this.vCoerce(this.vexpr(e),"vf32")}vEmitSwitchConsequent(e){const t=this.collectSwitchCaseStatements(e),s=this.vTerminated;this.vTerminated=!1;for(let e=0;e{const s=this.getType(t);switch(n){case"Number":case"Float":"Integer"===s?this.vCastValueToFloat(t):"LiteralInteger"===s?this.vCastLiteralToFloat(t):this.vCoerce(this.vexpr(t),"vf32");break;case"Integer":"Number"===s||"Float"===s?this.vCastValueToInteger(t):"LiteralInteger"===s?this.vCastLiteralToInteger(t):this.vCoerce(this.vexpr(t),"vi32");break;case"Boolean":this.vexprMask(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${n}`,e)}},a="Integer"===n?"vi32":"Boolean"===n?"vbool":"vf32";if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf("v128"),i(e.consequent),t.else_(),i(e.alternate),this.exit(),a;const o=t.addLocal("v128");this.vexprMask(e.test),t.localSet(o);const u=t.addLocal("v128");t.localGet(this.vCur).localSet(u);const l=t.addLocal("v128"),h=t.addLocal("v128");return t.localGet(u).localGet(o).v128And().localSet(this.vCur),this.vMaskDepth++,i(e.consequent),t.localSet(l),t.localGet(u).localGet(o).v128Andnot().localSet(this.vCur),i(e.alternate),t.localSet(h),this.vMaskDepth--,t.localGet(u).localSet(this.vCur),t.localGet(l).localGet(h).localGet(o).v128Bitselect(),a}vTernaryStatement(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementExpression(e.consequent),t.else_(),this.vstatementExpression(e.alternate),void this.exit();const s=t.addLocal("v128");this.vexprMask(e.test),t.localSet(s);const r=t.addLocal("v128");t.localGet(this.vCur).localSet(r),t.localGet(r).localGet(s).v128And().localSet(this.vCur),this.vMaskDepth++,this.vstatementExpression(e.consequent),t.localGet(r).localGet(s).v128Andnot().localSet(this.vCur),this.vstatementExpression(e.alternate),this.vMaskDepth--,t.localGet(r).localSet(this.vCur)}vexprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const s=this.isAstMathFunction(e);if(t=s||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);return s?this.vMathCall(t,e):this.vUserCall(t,e)}vUserCall(e,t){const s=this.em,r=this.assembler.helperInfo||{readsThread:!1,usesRandom:!1},n=this.assembler.globals,i=this.getType(t),a=this.lookupFunctionArgumentTypes(e)||[],o=[];for(let r=0;r0&&s.i32Const(t).i32Add(),s.globalSet(n.threadX)),r.usesRandom&&s.localGet(c).i32x4ExtractLane(t).globalSet(n.pcgState);for(const e of o)s.localGet(e.index),"vi32"===e.wtype?s.i32x4ExtractLane(t):s.f32x4ExtractLane(t);s.call(this.mangleFunctionName(e)),"void"!==u&&s.localSet(l),r.usesRandom&&s.localGet(c).globalGet(n.pcgState).i32x4ReplaceLane(t).localSet(c),"void"!==u&&(0===t?(s.localGet(l),"i32"===u?s.i32x4Splat():s.f32x4Splat(),s.localSet(h)):(s.localGet(h).localGet(l),"i32"===u?s.i32x4ReplaceLane(t):s.f32x4ReplaceLane(t),s.localSet(h)))}return r.readsThread&&s.localGet(this._vBaseX).globalSet(n.threadX),r.usesRandom&&(s.localGet(c).globalGet(n.pcgStateV),this.vMaskDepth>0?s.localGet(this.vCur):s.v128ConstI32x4(-1,-1,-1,-1),s.v128Bitselect().globalSet(n.pcgStateV)),"void"===u?"void":(s.localGet(h),"i32"===u?"vi32":"vf32")}vMathCall(e,t){const s=this.em;if("random"===e)return this.usesRandom=!0,this.vMaskDepth>0?s.localGet(this.vCur):s.v128ConstI32x4(-1,-1,-1,-1),s.call("pcg_random_v"),"vf32";const r=e=>{switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}},n=v[e];if(n)return r(t.arguments[0]),s[n](),"vf32";switch(e){case"round":return r(t.arguments[0]),s.v128ConstF32x4(.5,.5,.5,.5).f32x4Add().f32x4Floor(),"vf32";case"fround":return r(t.arguments[0]),"vf32";case"min":case"max":{const n="min"===e?"f32x4Min":"f32x4Max";r(t.arguments[0]);for(let e=1;e{s.localGet(e.indices[t]),"vec"===e.kind&&s.f32x4Splat()};if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return r(t.value),"vf32"}const n=s.addLocal("v128");this.vEmitIndex(t),s.localSet(n);const i=s.addLocal("v128");r(0),s.localSet(i);for(let t=1;tthis.isThreadDependent(e));switch(e.type){case"MemberExpression":{const t=this.getVariableSignature(e);if("this.thread.value"===t||"value.thread.value"===t)return"x"===e.property.name;break}case"CallExpression":if(this.isAstMathFunction(e)){if("random"===e.callee.property.name)return!0;break}return!0;case"Identifier":return!!this.taintedLocals&&this.taintedLocals.has(e.name);case"ThisExpression":return!1}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const s=e[t];if(s&&"object"==typeof s&&this.isThreadDependent(s))return!0}return!1}recordUniformity(e,t){this._analysisPass&&this.uniformity.push({kind:e,threadDependent:!t||this.isThreadDependent(t)})}}}}),ut=e((e,t)=>{let s=null;try{s=d()}catch(e){}const r="function"==typeof Worker;const n="\nvar entries = {};\nvar pipelines = {};\nfunction handleMessage(message, post) {\n if (message.type === 'setup') {\n var imports = { env: { memory: message.memory } };\n for (var i = 0; i < message.mathImports.length; i++) {\n imports.env['math_' + message.mathImports[i]] = Math[message.mathImports[i]];\n }\n var instance = new WebAssembly.Instance(message.module, imports);\n entries[message.id] = {\n run: instance.exports.run,\n runSimd: instance.exports.run_simd || null,\n sizeX: message.sizeX\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'pipelineSetup') {\n var instances = [];\n for (var i = 0; i < message.modules.length; i++) {\n var imports = { env: { memory: message.memory } };\n var math = message.moduleMathImports[i];\n for (var j = 0; j < math.length; j++) {\n imports.env['math_' + math[j]] = Math[math[j]];\n }\n instances.push(new WebAssembly.Instance(message.modules[i], imports));\n }\n var steps = [];\n for (var i = 0; i < message.steps.length; i++) {\n var exported = instances[message.steps[i].module].exports;\n steps.push({\n run: exported.run,\n runSimd: exported.run_simd || null,\n sizeX: message.steps[i].sizeX\n });\n }\n pipelines[message.id] = {\n steps: steps,\n i32: new Int32Array(message.memory.buffer),\n countIndex: message.countIndex,\n genIndex: message.genIndex,\n abortIndex: message.abortIndex\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'release') {\n delete entries[message.id];\n delete pipelines[message.id];\n } else if (message.type === 'run') {\n var entry = entries[message.id];\n var start = message.start;\n var end = message.end;\n var seed = message.seed;\n if (entry.runSimd && (entry.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) entry.runSimd(start, quadEnd, seed);\n if (quadEnd < end) entry.run(quadEnd, end, seed);\n } else {\n entry.run(start, end, seed);\n }\n post({ type: 'done', taskId: message.taskId });\n } else if (message.type === 'pipelineRun') {\n var pipeline = pipelines[message.id];\n var i32 = pipeline.i32;\n var gen = message.baseGen;\n var aborted = false;\n for (var s = 0; s < pipeline.steps.length && !aborted; s++) {\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n var step = pipeline.steps[s];\n var start = message.ranges[s * 2];\n var end = message.ranges[s * 2 + 1];\n var seed = message.seeds[s];\n if (end > start) {\n if (step.runSimd && (step.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) step.runSimd(start, quadEnd, seed);\n if (quadEnd < end) step.run(quadEnd, end, seed);\n } else {\n step.run(start, end, seed);\n }\n }\n gen++;\n if (Atomics.add(i32, pipeline.countIndex, 1) + 1 === message.workerCount) {\n Atomics.store(i32, pipeline.countIndex, 0);\n Atomics.store(i32, pipeline.genIndex, gen);\n Atomics.notify(i32, pipeline.genIndex);\n } else {\n for (;;) {\n if (Atomics.load(i32, pipeline.genIndex) >= gen) break;\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n Atomics.wait(i32, pipeline.genIndex, gen - 1, 100);\n }\n }\n }\n post({ type: 'done', taskId: message.taskId, aborted: aborted });\n }\n}\nif (typeof self !== 'undefined' && typeof postMessage === 'function') {\n self.onmessage = function(event) {\n handleMessage(event.data, function(message) { postMessage(message); });\n };\n} else {\n var parentPort = require('worker_threads').parentPort;\n parentPort.on('message', function(message) {\n handleMessage(message, function(reply) { parentPort.postMessage(reply); });\n });\n}\n";t.exports={WebAssemblyWorkerPool:class{constructor(e){this.size=e||function(){if("undefined"!=typeof navigator&&navigator.hardwareConcurrency)return navigator.hardwareConcurrency;if(s&&"function"==typeof s.cpus){const e=s.cpus().length;if(e)return e}return 4}(),this.workers=[],this.destroyed=!1,this.dispatchCount=0,this.lastDispatch=null,this._taskId=0}get liveWorkerCount(){let e=0;for(const t of this.workers)t.dead||e++;return e}_spawn(){const e={handle:null,dead:!1,state:{setup:new Set,settingUp:new Map,pending:new Map},fail:null,die:null},t=e.state;e.fail=e=>{for(const s of t.settingUp.values())s.reject(e);t.settingUp.clear();for(const s of t.pending.values())s.reject(e);t.pending.clear()},e.die=t=>{if(!e.dead&&(e.dead=!0,e.fail(t),e.handle&&"function"==typeof e.handle.terminate))try{e.handle.terminate()}catch(e){}};const s=s=>{if("ready"===s.type){const r=t.settingUp.get(s.id);r&&(t.settingUp.delete(s.id),t.setup.add(s.id),this._updateRef(e),r.resolve())}else if("done"===s.type){const r=t.pending.get(s.taskId);r&&(t.pending.delete(s.taskId),this._updateRef(e),r.resolve())}};let i;if(r){const t=URL.createObjectURL(new Blob([n],{type:"text/javascript"}));i=new Worker(t),URL.revokeObjectURL(t),i.onmessage=e=>s(e.data),i.onerror=t=>e.die(new Error(t.message||"WebAssembly worker error"))}else{const{Worker:t}=d();i=new t(n,{eval:!0}),i.on("message",s),i.on("error",t=>e.die(t)),i.on("exit",t=>{e.die(new Error(`WebAssembly worker exited with code ${t}`))}),i.unref()}return e.handle=i,e}_worker(e){for(;this.workers.length<=e;)this.workers.push(this._spawn());return this.workers[e].dead&&(this.workers[e]=this._spawn()),this.workers[e]}_updateRef(e){!e.dead&&e.handle&&"function"==typeof e.handle.ref&&(e.state.settingUp.size+e.state.pending.size>0?e.handle.ref():e.handle.unref())}_ensureSetup(e,t){if(e.state.setup.has(t.id))return Promise.resolve();let s=e.state.settingUp.get(t.id);return s||(s={},s.promise=new Promise((e,t)=>{s.resolve=e,s.reject=t}),e.state.settingUp.set(t.id,s),this._updateRef(e),e.handle.postMessage(t.pipeline?{type:"pipelineSetup",id:t.id,memory:t.memory,modules:t.modules,moduleMathImports:t.moduleMathImports,steps:t.steps,countIndex:t.countIndex,genIndex:t.genIndex,abortIndex:t.abortIndex}:{type:"setup",id:t.id,module:t.module,memory:t.memory,mathImports:t.mathImports,sizeX:t.sizeX})),s.promise}dispatch(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:t.length,ranges:t.map(e=>[e.start,e.end])};const s=t.map((t,s)=>{const r=this._worker(s);return this._ensureSetup(r,e).then(()=>new Promise((s,n)=>{if(r.dead)return void n(new Error("WebAssembly worker died before the task could run"));const i=++this._taskId;r.state.pending.set(i,{resolve:s,reject:n}),this._updateRef(r),r.handle.postMessage({type:"run",id:e.id,taskId:i,start:t.start,end:t.end,seed:t.seed})}))});return Promise.all(s).then(()=>{})}dispatchPipeline(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:e.workerCount,ranges:e.workerRanges.map(e=>e.slice())};const s=[];for(let r=0;rnew Promise((s,i)=>{if(n.dead)return void i(new Error("WebAssembly worker died before the task could run"));const a=++this._taskId;n.state.pending.set(a,{resolve:s,reject:i}),this._updateRef(n),n.handle.postMessage({type:"pipelineRun",id:e.id,taskId:a,ranges:e.workerRanges[r],seeds:t.seeds,baseGen:t.baseGen,workerCount:e.workerCount})})))}return Promise.all(s).then(()=>{})}release(e){if(!this.destroyed)for(const t of this.workers){if(t.dead)continue;t.state.setup.delete(e);const s=t.state.settingUp.get(e);s&&(t.state.settingUp.delete(e),s.reject(new Error("WebAssembly kernel entry released during setup")),this._updateRef(t)),t.handle.postMessage({type:"release",id:e})}}destroy(){if(this.destroyed)return;this.destroyed=!0;const e=new Error("WebAssembly worker pool has been destroyed");for(const t of this.workers)t.dead=!0,t.fail(e),t.handle.terminate();this.workers=[]}}}}),lt=e((e,t)=>{const{Kernel:s}=a(),{FunctionBuilder:n}=o(),{WebAssemblyFunctionNode:u}=ot(),{WasmModuleBuilder:l}=at(),{WebAssemblyWorkerPool:h}=ut(),{utils:c}=i(),{Input:p}=r(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0});let f=null,m=null,g=1;t.exports={WebAssemblyKernel:class e extends s{static get isSupported(){return"object"==typeof WebAssembly&&null!==WebAssembly&&WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0]))}static get isSIMDSupported(){if(null===f)try{const e=new l;e.addFunction("t",{params:[],results:[]}).v128ConstI32x4(0,0,0,0).drop(),f=WebAssembly.validate(e.toBytes())}catch(e){f=!1}return f}static get isThreadsSupported(){if(null===m)try{if("undefined"==typeof SharedArrayBuffer)m=!1;else{const e=new l;e.addMemoryImport(1,1,!0);const t=new WebAssembly.Memory({initial:1,maximum:1,shared:!0});new WebAssembly.Instance(new WebAssembly.Module(e.toBytes()),{env:{memory:t}}),m=!0}}catch(e){m=!1}return m}static isContextMatch(e){return!1}static getFeatures(){return d}static get features(){return d}static get mode(){return"webasm"}static getSignature(e,t){return"webasm"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static dispatchSpans(e,t,s,r,n){if(!t||0===s)return e(0,s,n),"scalar";if(!(3&r))return t(0,s,n),"simd";const i=-4&r,a=s/r;for(let s=0;s0&&t(a,a+i,n),e(a+i,a+r,n)}return i>0?"simd+scalar-tail":"scalar"}static nativeFunctionArguments(){throw new Error("WebAssembly backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebAssembly backend does not yet support native functions")}static combineKernels(){throw new Error("WebAssembly backend does not yet support combineKernels")}constructor(e,t){super(e,t),this.poolSize=null,this.mergeSettings(e.settings||t),null===this.precision&&(this.precision="single"),this.threadDim=null,this.componentCount=1,this.moduleCacheLimit=8,this.functionBuilder=null,this.tracedFunctions=null,this.usesRandom=!1,this.usedMathImports=null,this._moduleCache=new Map,this._active=null,this._lastRunPath=null,this._pool=null,this._threadedTail=Promise.resolve(),this._threadedBusy=0,this._threadedEpoch=0}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built&&!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");return this.output=t,this}toString(){throw new Error("WebAssembly backend does not yet support toString")}build(){if(this.built)return;if(this.gpu&&this.gpu.kernels&&-1===this.gpu.kernels.indexOf(this)&&this.gpu.kernels.push(this),this.graphical)return this.requestFallback(arguments,"graphical mode is not supported on the webasm backend");if(this.subKernels&&this.subKernels.length>0)return this.requestFallback(arguments,"kernel maps are not supported on the webasm backend");this.setupConstants(),this.setupArguments(arguments);for(let e=0;e16*Math.ceil(e/16);let s=0;const r={},n={};for(let i=0;i=4096}_entryKey(e){return this._computeSizeSignature(e)+(this._threadable()?"|shared":"")}_assembleModule(t,s,r){const n=new l,i=t.totalBytes||t.outputOffset+s*this.componentCount*4,a=Math.ceil(i/65536)+16,o=Math.max(a,4096);n.addMemoryImport(a,o,r);const u=Array.from(this.usedMathImports).sort();for(const e of u){const t="pow"===e||"atan2"===e?["f32","f32"]:["f32"];n.addFuncImport("math_"+e,t,["f32"])}const h={threadX:n.addGlobal("i32",!0,0),threadY:n.addGlobal("i32",!0,0),threadZ:n.addGlobal("i32",!0,0),dataIndex:n.addGlobal("i32",!0,0)};this.usesRandom&&(h.pcgState=n.addGlobal("i32",!0,0),this._emitPcgRandom(n,h.pcgState));const c={module:n,layout:t,globals:h};for(let e=this.tracedFunctions.length-1;e>=0;e--){const t=this.tracedFunctions[e];if("kernel"===t)continue;const s=this.functionBuilder.functionMap[t];s&&(s.output=this.output,s.emitFunction(c))}this.functionBuilder.functionMap.kernel.output=this.output,this.functionBuilder.functionMap.kernel.emitFunction(c);const[p,d]=this.threadDim,f=n.addFunction("run",{params:["i32","i32","i32"],locals:["i32"]});if(f.localGet(0).localSet(3),1===this.output.length?(f.i32Const(0).globalSet(h.threadY),f.i32Const(0).globalSet(h.threadZ)):2===this.output.length&&f.i32Const(0).globalSet(h.threadZ),f.block(),f.localGet(3).localGet(1).i32GeS().brIf(0),f.loop(),f.localGet(3).globalSet(h.dataIndex),1===this.output.length?f.localGet(3).globalSet(h.threadX):2===this.output.length?(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().globalSet(h.threadY)):(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().i32Const(d).i32RemU().globalSet(h.threadY),f.localGet(3).i32Const(p*d).i32DivU().globalSet(h.threadZ)),this.usesRandom&&f.localGet(2).localGet(3).i32Const(-1640531527).i32Mul().i32Add().i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(h.pcgState),f.call("kernel"),f.localGet(3).i32Const(1).i32Add().localSet(3),f.localGet(3).localGet(1).i32LtS().brIf(0),f.end(),f.end(),n.exportFunction("run"),e.isSIMDSupported){this.usesRandom&&(h.pcgStateV=n.addGlobal("v128",!0,0),this._emitPcgRandomVector(n,h.pcgStateV));let e=null;for(const t of this.tracedFunctions){if("kernel"===t)continue;const s=this.functionBuilder.functionMap[t];s&&(e||(e={readsThread:!1,usesRandom:!1}),s.readsThread&&(e.readsThread=!0),s.usesRandom&&(e.usesRandom=!0))}c.helperInfo=e,this.functionBuilder.functionMap.kernel.emitVectorFunction(c),this._emitRunSimd(n,h),n.exportFunction("run_simd")}return{bytes:n.toBytes(),initial:a,maximum:o}}_emitRunSimd(e,t){const[s,r]=this.threadDim,n=e.addFunction("run_simd",{params:["i32","i32","i32"],locals:["i32"]});n.localGet(0).localSet(3),1===this.output.length?(n.i32Const(0).globalSet(t.threadY),n.i32Const(0).globalSet(t.threadZ)):2===this.output.length&&n.i32Const(0).globalSet(t.threadZ),n.block(),n.localGet(3).localGet(1).i32GeS().brIf(0),n.loop(),n.localGet(3).globalSet(t.dataIndex),1===this.output.length?n.localGet(3).globalSet(t.threadX):2===this.output.length?(n.localGet(3).i32Const(s).i32RemU().globalSet(t.threadX),n.localGet(3).i32Const(s).i32DivU().globalSet(t.threadY)):(n.localGet(3).i32Const(s).i32RemU().globalSet(t.threadX),n.localGet(3).i32Const(s).i32DivU().i32Const(r).i32RemU().globalSet(t.threadY),n.localGet(3).i32Const(s*r).i32DivU().globalSet(t.threadZ)),this.usesRandom&&(n.localGet(3).i32x4Splat().v128ConstI32x4(0,1,2,3).i32x4Add(),n.v128ConstI32x4(-1640531527,-1640531527,-1640531527,-1640531527).i32x4Mul(),n.localGet(2).i32x4Splat().i32x4Add(),n.v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul(),n.v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add(),n.globalSet(t.pcgStateV)),n.call("kernel_simd"),n.localGet(3).i32Const(4).i32Add().localSet(3),n.localGet(3).localGet(1).i32LtS().brIf(0),n.end(),n.end()}_emitPcgRandomVector(e,t){const s=e.addFunction("pcg_random_v",{params:["v128"],results:["v128"]}),r=s.addLocal("v128"),n=s.addLocal("i32");s.globalGet(t).v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul().v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add().globalGet(t).localGet(0).v128Bitselect().globalSet(t),s.globalGet(t).localSet(r),s.localGet(r).i32x4ExtractLane(0).localSet(n),s.localGet(n).localGet(n).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4Splat();for(let e=1;e<4;e++)s.localGet(r).i32x4ExtractLane(e).localSet(n),s.localGet(n).localGet(n).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4ReplaceLane(e);s.localGet(r).v128Xor(),s.v128ConstI32x4(277803737,277803737,277803737,277803737).i32x4Mul();const i=s.addLocal("v128");s.localTee(i),s.i32Const(22).i32x4ShrU().localGet(i).v128Xor(),s.i32Const(8).i32x4ShrU(),s.f32x4ConvertI32x4U(),s.v128ConstF32x4(16777216,16777216,16777216,16777216).f32x4Div()}_emitPcgRandom(e,t){const s=e.addFunction("pcg_random",{params:[],results:["f32"]}),r=s.addLocal("i32");s.globalGet(t).i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(t),s.globalGet(t).globalGet(t).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().globalGet(t).i32Xor().i32Const(277803737).i32Mul().localTee(r),s.i32Const(22).i32ShrU().localGet(r).i32Xor().i32Const(8).i32ShrU().f32ConvertI32U().f32Const(16777216).f32Div()}_releaseEntry(e){const t=()=>{e.instance=null,e.module=null,e.memory=null,e.run=null,e.runSimd=null,e.f32=null,e.i32=null,e.bytes=null};if(e.shared&&this._pool){const s=this._pool;this._threadedTail.then(()=>{s.release(e.id),t()},t)}else t()}_instantiate(e,t){let s=this._moduleCache.get(e);if(s&&(this._moduleCache.delete(e),this._moduleCache.set(e,s)),!s){const r=this._threadable(),n=this.computeLayout(t),[i,a,o]=this.threadDim,u=i*a*o,{bytes:l,initial:h,maximum:d}=this._assembleModule(n,u,r);if(!WebAssembly.validate(l))throw new Error("WebAssembly backend: generated module failed validation (internal error)");const f=r?new WebAssembly.Memory({initial:h,maximum:d,shared:!0}):new WebAssembly.Memory({initial:h,maximum:d}),m={env:{memory:f}};for(const e of this.usedMathImports)m.env["math_"+e]=Math[e];const y=new WebAssembly.Module(l),x=new WebAssembly.Instance(y,m);s={id:g++,sizeSignature:e,shared:r,layout:n,cells:u,bytes:l,module:y,memory:f,mathImports:Array.from(this.usedMathImports).sort(),sizeX:i,instance:x,run:x.exports.run,runSimd:x.exports.run_simd||null,f32:new Float32Array(f.buffer),i32:new Int32Array(f.buffer)};for(const e in n.constantArrays){const t=n.constantArrays[e],r=this.constants[e];c.flattenTo(r instanceof p?r.value:r,s.f32.subarray(t.offset/4,t.offset/4+t.flatLength))}for(this._moduleCache.set(e,s);this._moduleCache.size>Math.max(this.moduleCacheLimit,1);){const e=this._moduleCache.keys().next().value,t=this._moduleCache.get(e);this._moduleCache.delete(e),this._releaseEntry(t)}}this._active=s}checkArgumentTypes(e){if(super.checkArgumentTypes(e),!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let s=0;s>>0:4294967296*Math.random()>>>0),l|=0,this._lastRunPath=e.dispatchSpans(o,u,n,t[0],l);const h=r.outputOffset/4,d=i.slice(h,h+n*this.componentCount);return this._shapeOutput(d,Array.from(this.output),this.componentCount)}_runThreaded(e){const t=this._active,{layout:s,cells:r}=t,n=0===this._threadedBusy;let i=null,a=null;if(n){for(const r in s.arrays){const n=s.arrays[r],i=e[n.index];c.flattenTo(i instanceof p?i.value:i,t.f32.subarray(n.offset/4,n.offset/4+n.flatLength))}for(const r in s.scalars){const n=s.scalars[r],i=e[n.index];"Integer"===n.type?t.i32[n.offset/4]=0|i:"Boolean"===n.type?t.i32[n.offset/4]=i?1:0:t.f32[n.offset/4]=i}}else{i=[];for(const t in s.arrays){const r=s.arrays[t],n=e[r.index],a=new Float32Array(r.flatLength);c.flattenTo(n instanceof p?n.value:n,a),i.push({record:r,flat:a})}a=[];for(const t in s.scalars){const r=s.scalars[t];a.push({record:r,value:e[r.index]})}}let o=0;this.usesRandom&&(o=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0),o|=0,this._pool||(this._pool=new h(this.poolSize||void 0));const u=this._pool,l=this.componentCount,d=Array.from(this.output);this._threadedBusy++;const f=this._threadedTail.then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");if(i){for(let e=0;e=r)break;h.push({start:s,end:t===e-1?r:Math.min(s+n,r),seed:o})}return this._lastRunPath="threaded",u.dispatch(t,h).then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");const e=s.outputOffset/4,n=t.f32.slice(e,e+r*l);return this._shapeOutput(n,d,l)})}),m=this._threadedEpoch,g=()=>{this._threadedEpoch===m&&this._threadedBusy--};return this._threadedTail=f.then(g,g),f}_shapeOutput(e,t,s){const[r,n,i]=[t[0],t[1]||1,t[2]||1];if(1===s)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,r);case 2:return c.erectMemoryOptimized2DFloat(e,r,n);default:return c.erectMemoryOptimized3DFloat(e,r,n,i)}const a=s,o=t=>{const s=new Array(r);for(let n=0;n{const{utils:s}=i(),{Input:n}=r(),{WebAssemblyKernel:a}=lt(),{WebAssemblyWorkerPool:o}=ut(),u=["Array","Input","Number","Float","Integer","Boolean"];let l=1;var h=class extends Error{constructor(e,t){super(e),this.isFusionFallback=!0,this.recompilable=Boolean(t)}};function c(e){return e&&"function"==typeof e.toArray?e.toArray():e}function p(e){const t=e instanceof n?Array.from(e.size):Array.from(s.getDimensions(e));for(;t.length<3;)t.push(1);return t}function d(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}t.exports={WebAssemblyPipelineExecutor:class e{static compile(t,s,r){for(let e=0;es.getVariableType(e,h)).join(",");let d=r.get(p);if(!d){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(o.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=o.clone.kernel;this._prepareKernel(e,l),d={id:r.size,kernel:e,constantRegions:null},r.set(p,d)}u[n]=d,c[n]=l}for(let e=0;e{const t=p;return p=(e=>16*Math.ceil(e/16))(p+e),t};let f=0,m=-1;if(!this.pipeline._threadsDisabled&&a.isThreadsSupported){let e=0;for(let s=0;se&&(e=n)}const s=new o;f=Math.min(s.size,Math.ceil(e/4096)),f>1?(this.threaded=!0,this.kind="fused-threaded",this.pool=s,m=d(12)):s.destroy()}const g=new Map,y=new Map,x=new Map,b=[],v=[],S=[],T=new Array(t.steps.length);for(let e=0;e${i}`;let l=E.get(o);if(!l){const a={arrays:n.arrays,scalars:n.scalars,constantArrays:s.constantRegions,outputOffset:i,totalBytes:_},u=w[t.steps[e].outputBuffer].cells,h=r._assembleModule(a,u,this.threaded);null===this.memory&&(this.memory=this.threaded?new WebAssembly.Memory({initial:h.initial,maximum:h.maximum,shared:!0}):new WebAssembly.Memory({initial:h.initial,maximum:h.maximum}),this.f32=new Float32Array(this.memory.buffer),this.i32=new Int32Array(this.memory.buffer));const c={env:{memory:this.memory}};for(const e of r.usedMathImports)c.env["math_"+e]=Math[e];const p=new WebAssembly.Module(h.bytes),d=new WebAssembly.Instance(p,c);l={run:d.exports.run,runSimd:d.exports.run_simd||null,moduleIndex:k.length},k.push(p),C.push(Array.from(r.usedMathImports).sort()),E.set(o,l)}I[e]={run:l.run,runSimd:l.runSimd,moduleIndex:l.moduleIndex,cells:w[t.steps[e].outputBuffer].cells,sizeX:r.threadDim[0],usesRandom:r.usesRandom,randomSeed:r.randomSeed}}if(this.threaded){const e=[];for(let s=0;s=t?(r[2*e]=0,r[2*e+1]=0):(r[2*e]=i,r[2*e+1]=s===f-1?t:Math.min(i+n,t))}e.push(r)}this._entry={id:"pipeline:"+l++,pipeline:!0,memory:this.memory,modules:k,moduleMathImports:C,steps:I.map(e=>({module:e.moduleIndex,sizeX:e.sizeX})),countIndex:m/4,genIndex:m/4+1,abortIndex:m/4+2,workerCount:f,workerRanges:e}}for(let e=0;e{const s=e.binding;if("step"===s.source){const e=s.step,r=w[t.steps[e].outputBuffer],n=u[e].kernel;return{kind:"step",base:r.offset/4,count:r.cells*n.componentCount,output:t.steps[e].output,componentCount:n.componentCount,kernel:n}}return"pipelineArg"===s.source?{kind:"arg",index:s.index}:{kind:"literal",value:s.value}}),this._stepRuns=I,this._argArrayRegions=g,this._argScalarSlots=y,this._scratch=null}_representativeArgs(e,t){const s=new Array(e.argBindings.length);for(let r=0;r>>0:4294967296*Math.random()>>>0):0}_executeThreaded(e){const t=this._entry,s=this.i32,r=this._stepRuns.map(e=>this._drawSeed(e));this._lastRunAborted&&(Atomics.store(s,t.countIndex,0),Atomics.store(s,t.abortIndex,0),this._lastRunAborted=!1,this._abortError=null);const n=Atomics.load(s,t.genIndex),i=n+this._stepRuns.length;return this.pool.dispatchPipeline(t,{baseGen:n,seeds:r}).then(null,e=>this._abort(e)),this._waitForGeneration(i).then(()=>this._readResults(e))}_waitForGeneration(e){const t=this.i32,s=this._entry.genIndex,r="function"==typeof Atomics.waitAsync?Atomics.waitAsync:null;return new Promise((n,i)=>{const a="function"==typeof setInterval?setInterval(()=>{},200):null,o=(e,t)=>{null!==a&&clearInterval(a),e(t)},u=this._entry.countIndex;let l=Atomics.load(t,s),h=Atomics.load(t,u),c=Date.now();const p=()=>{if(this._abortError)return void o(i,this._abortError);const a=Atomics.load(t,s);if(a>=e)return void o(n);const d=Atomics.load(t,u);if(a!==l||d!==h)l=a,h=d,c=Date.now();else if(Date.now()-c>=this.sanityTimeoutMs){const t=new Error(`pipeline threaded barrier stalled at generation ${a} of ${e} for ${this.sanityTimeoutMs}ms`);return this._abort(t),void o(i,t)}if(r){const e=Math.max(1,Math.min(200,this.sanityTimeoutMs)),n=r(t,s,a,e);n.async?n.value.then(p):Promise.resolve().then(p)}else setTimeout(p,1)};p()})}_abort(e){if(!this._abortError&&(this._abortError=e||new Error("pipeline threaded run aborted"),this._lastRunAborted=!0,this.i32&&this._entry&&(Atomics.store(this.i32,this._entry.abortIndex,1),Atomics.notify(this.i32,this._entry.genIndex)),this.pool&&this.pool.workers))for(const e of this.pool.workers)!e.dead&&e.state.pending.size>0&&e.die(this._abortError)}abortRuns(e){this.threaded&&this._abort(e)}_readResults(e){const t=this.f32,s=this.plan.results,r=new Array(this._resultReads.length);for(let s=0;s{const{utils:s}=i(),{Input:n}=r(),{FusionFallback:a}=ht();function o(e){return e&&"function"==typeof e.toArray?e.toArray():e}function u(e,t,s){const r=e.limits,n=Math.min(r.maxStorageBufferBindingSize,r.maxBufferSize);if(t>n)throw new a(`${s} needs ${t} bytes but this device allows ${n} per storage buffer`)}function l(e){const t=e instanceof n?Array.from(e.size):Array.from(s.getDimensions(e));for(;t.length<3;)t.push(1);return t}function h(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}function c(e){return Boolean(e)&&"object"==typeof e&&!(e instanceof n)&&("function"==typeof e.toArray||"function"==typeof e.delete)}t.exports={WebGPUPipelineExecutor:class e{static async compile(t,s,r){for(let e=0;es.getVariableType(e,h)).join(",");let p=r.get(c);if(!p){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(u.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=u.clone.kernel;await this._prepareKernel(e,l),p={id:r.size,kernel:e},r.set(c,p)}o[n]=p}this._scratch=null;for(let e=0;e{const s=e.output;let r=1;for(let e=0;e{let t=f.get(e);return void 0===t&&(t=f.size,f.set(e,t)),t},g=new Map;this._passes=new Array(t.steps.length);for(let r=0;r{const t=i.argBindings[e.index];return"literal"===t.source?"l"+t.value:"a"+t.index}).join(","),S=null!==f.randomSeedOffset&&null===d.randomSeed,T=c.id+":"+y.map(m).join(",")+">"+m(b)+":"+v+(S?"#"+r:"");let A=g.get(T);if(!A){const e=new ArrayBuffer(f.byteLength),t=new Uint32Array(e),s=new Int32Array(e),r=new Float32Array(e),n=d._computeDispatch(d.threadDim);t[0]=d.threadDim[0],t[1]=d.threadDim[1],t[2]=d.threadDim[2],t[3]=n.dispatchWidth;for(let e=0;e>>0);const u=h.createBuffer({size:f.byteLength,usage:72}),l=o.length>0||S;l||p.writeBuffer(u,0,e);const c=[{binding:0,resource:{buffer:u}}];for(let e=0;e{const s=e.binding;if("step"===s.source){const e=t.steps[s.step],r=this._planBuffers[e.outputBuffer],n=o[s.step].kernel,i=r.cells*n.componentCount*4,a={kind:"step",buffer:r.buffer,offset:y,byteLength:i,output:e.output,componentCount:n.componentCount,kernel:n};return y+=function(e){return 16*Math.ceil(e/16)}(i),a}return"pipelineArg"===s.source?{kind:"arg",index:s.index}:{kind:"literal",value:s.value}}),y>0&&(this._staging=h.createBuffer({size:y,usage:9}))}_representativeArgs(e,t){const s=new Array(e.argBindings.length);for(let r=0;r>>0),r.writeBuffer(s.paramsBuffer,0,s.mirror)}}const i=t.createCommandEncoder();for(let e=0;e{const t=this._staging.getMappedRange(),s=this._shapeResults(e,t);return this._staging.unmap(),s}):Promise.resolve(this._shapeResults(e,null))}_shapeResults(e,t){const s=this.plan.results,r=new Array(this._resultReads.length);for(let s=0;s{const{Input:s}=r(),{utils:n}=i(),a="pipeline intermediate results cannot be read during orchestration",o="a pipeline must return a handle, or an Array or plain object of handles",u="pipeline has been destroyed",l="the orchestration function must be synchronous; async functions and generators cannot be traced",h="this handle belongs to a different trace; handles do not survive re-trace or cross pipelines";var c=class{};let p=null;var d=class{constructor(e){this.gpu=e,this.steps=[],this.kernels=[],this.kernelIndexes=new Map,this.handleMeta=new WeakMap,this.held=[]}createHandle(e){const t=Object.freeze(new c),s=new Proxy(t,{get(e,t){if(t===Symbol.toPrimitive||"valueOf"===t||"toString"===t)return()=>{throw new Error("pipeline intermediate results cannot be used in arithmetic or conditions during orchestration")};throw new Error(a)},set(){throw new Error(a)},ownKeys(){throw new Error(a)},has(){throw new Error(a)},getOwnPropertyDescriptor(){throw new Error(a)}});return this.handleMeta.set(s,e),s}recordKernelCall(e,t){const s=e.kernel;if(s.gpu!==this.gpu)throw new Error("pipelines can only call kernels created by the same GPU instance");if(s.graphical)throw new Error("graphical kernels are not supported inside pipelines");if(s.subKernels&&s.subKernels.length>0)throw new Error("kernel maps are not supported inside pipelines");if(!s.output)throw new Error("kernels called inside a pipeline must have a fixed output size");let r=this.kernelIndexes.get(e);void 0===r&&(r=this.kernels.length,this.kernels.push(e),this.kernelIndexes.set(e,r));const n=new Array(t.length);for(let e=0;ef(e,t)):e}function m(e){for(let t=0;t{if(this.destroyed)throw new Error(u);if(this.plan||(this.plan=this._buildPlan(),this._executor=void 0),void 0===this._executor&&await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;if(this._dropExecutor(),e.recompilable){if(await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;this._dropExecutor(),this._degrade(e.message)}}else this._degrade(e.message)}return this._executeGeneric(this.plan,t,r)}),i=()=>{this._inFlight--,s.length>0&&m(s)};return n.then(i,i),this._tail=n.then(b,b),n}_guardAsync(e){return e&&"function"==typeof e.then?e.then(null,e=>{throw this._dropExecutor(),e}):e}setConstants(e){this.constants=Object.assign({},e||{});const t=()=>{this._releasePlan()};return this._tail=this._tail.then(t,t),this}destroy(){if(this.destroyed=!0,this.gpu&&this.gpu.pipelines){const e=this.gpu.pipelines.indexOf(this);-1!==e&&this.gpu.pipelines.splice(e,1)}this._executor&&"function"==typeof this._executor.abortRuns&&this._executor.abortRuns(new Error(u));const e=()=>{this._releasePlan()},t=this._tail.then(e,e);return this._tail=t,t}_buildPlan(){const e=new d(this.gpu),t=new Array(this.argumentCount);for(let s=0;s({key:s,binding:e.bindValue(t)}))};if(t instanceof c)throw new Error(h);if("object"==typeof t&&!ArrayBuffer.isView(t)){if("function"==typeof t.then)throw new Error(l);const s=Object.getPrototypeOf(t);if(s!==Object.prototype&&null!==s)throw new Error(o);const r=[];for(const s in t)t.hasOwnProperty(s)&&r.push({key:s,binding:e.bindValue(t[s])});if(0===r.length)throw new Error(o);return{kind:"object",entries:r}}throw new Error(o)}(e,r),i=function(e,t){const s=new Array(e.length).fill(-1);for(let t=0;te.binding)),a=e.kernels.map(e=>({shortcut:e,clone:this._cloneKernel(e)}));return{steps:e.steps,buffers:i,results:n,kernels:a,held:e.held,genericClones:new Map}}_genericClone(e,t){const s=t.argBindings.map(e=>"step"===e.source?"T":"pipelineArg"===e.source?"a"+e.index:"l").join(","),r=t.kernel+":"+t.outputBuffer+":"+s;let n=e.genericClones.get(r);return n||(n=this._cloneKernel(e.kernels[t.kernel].clone,{immutable:!1,dynamicArguments:!1}),e.genericClones.set(r,n)),n}_prepareExecutor(e){if(this._fusionDisabled)return void(this._executor=!1);const t=this.plan.kernels;if(t.length>0&&"webgpu"===t[0].clone.kernel.constructor.mode){const{WebGPUPipelineExecutor:t}=ct();return t.compile(this,this.plan,e).then(e=>{this._executor=e,this.executorKind=e.kind,this.fallbackReason=null},e=>{this._degrade(e&&e.message||"fused executor unavailable")})}try{const{WebAssemblyPipelineExecutor:t}=ht();this._executor=t.compile(this,this.plan,e),this.executorKind=this._executor.kind,this.fallbackReason=null}catch(e){this._degrade(e&&e.message||"fused executor unavailable")}}_dropExecutor(){this._executor&&this._executor.destroy(),this._executor=void 0}_degrade(e){this._executor=!1,this.executorKind="generic",this.fallbackReason=e}_cloneKernel(e,t){const s=e.kernel,r=Object.assign({output:Array.from(s.output),pipeline:!0,immutable:!0,dynamicArguments:!0},t||{}),n=["constants","constantTypes","precision","loopMaxIterations","strictIntegers","fixIntegerDivisionAccuracy","optimizeFloatMemory","tactic","functions","nativeFunctions","injectedNative","debug","randomSeed","returnType"];s.declaredArgumentTypes&&(r.argumentTypes=s.declaredArgumentTypes.slice());for(let e=0;e1?"function (v) { return v[this.thread.z][this.thread.y][this.thread.x]; }":t[1]>1?"function (v) { return v[this.thread.y][this.thread.x]; }":"function (v) { return v[this.thread.x]; }",a=t[2]>1?[t[0],t[1],t[2]]:t[1]>1?[t[0],t[1]]:[t[0]];n=this.gpu.createKernel(i,{output:a,pipeline:!0,immutable:!1}),e.genericClones.set(r,n)}return n(s)}_genericEagerUploadsPay(e){return 0!==e.kernels.length&&"gpu"===e.kernels[0].clone.kernel.constructor.mode}_eagerUploads(e,t){const r=new Array(t.length).fill(null);for(let n=0;n0?e.kernels[0].clone.kernel.constructor.mode:null,a="gpu"===i||"webgpu"===i,o=r||new Array(t.length).fill(null);if(a&&!r)for(let r=0;r{const{utils:s}=i(),{Input:n}=r(),{getActiveTrace:a}=pt();function o(e,t){if(t.kernel)return void(t.kernel=e);const r=s.allPropertiesOf(e);for(let s=0;st.kernel[n]),t.__defineSetter__(n,e=>{t.kernel[n]=e})))}t.kernel=e}t.exports={kernelRunShortcut:function(e){function t(t){e.build.apply(e,t),e.checkArgumentTypes(t);let r=e.switchingKernels?void 0:e.run.apply(e,t);for(let n=0;e.switchingKernels;n++){if(n>=4){const t=e.resetSwitchingKernels();throw new Error(`this kernel cannot run the arguments it was given (${s(t)}); it did not settle on a kernel for them after 4 attempts. Create a separate kernel for this call's argument types.`)}const i=e.resetSwitchingKernels(),a=e.onRequestSwitchKernel(i,t,e);p.kernel=e=a,a.checkArgumentTypes(t),r=a.switchingKernels?void 0:a.run.apply(a,t),a.fallbackRequested&&(r=e.run.apply(e,t))}return r}function s(e){return e&&e.length?e.map(e=>"argumentTypeMismatch"===e.type?`argument ${e.index} is now ${e.needed}`:e.type).join(", "):"unknown reason"}function r(s){if(e.onAsyncModeUpgrade){const t=e.onAsyncModeUpgrade;e.onAsyncModeUpgrade=null;const n=l(s);return t(n,e).then(e=>(e&&p.replaceKernel(e),r(n)))}try{if(!0===e.constructor.isAsync)return e.build.apply(e,s),Promise.resolve(e.run.apply(e,s));for(let e=0;er(e));const n=t(s);return e.renderKernels?Promise.resolve(e.renderKernels()):e.renderOutput?e.renderOutputAsync?e.renderOutputAsync():Promise.resolve(e.renderOutput()):Promise.resolve(n)}catch(e){return Promise.reject(e)}}function i(e){return Boolean(e)&&"WebGPUBuffer"===e.type}function u(e){const t=l(e),s=[];for(let e=0;e{t[r]=e}))}return Promise.all(s).then(()=>t)}function l(e){const t=new Array(e.length);for(let s=0;s{try{e(c.apply(this,arguments))}catch(e){t(e)}})},p.replaceKernel=function(t){o(e=t,p)},o(e,p),p}}}),ft=e((e,s)=>{const{gpuMock:r}=t(),{utils:n}=i(),{Kernel:o}=a(),{CPUKernel:u}=p(),{HeadlessGLKernel:l}=ve(),{WebGL2Kernel:h}=tt(),{WebGLKernel:c}=be(),{WebGPUKernel:d}=it(),{WebAssemblyKernel:f}=lt(),{kernelRunShortcut:m}=dt(),{Pipeline:g}=pt(),y=[l,h,c,f],x=["gpu","cpu"],b={headlessgl:l,webgl2:h,webgl:c,webgpu:d,webasm:f};let v=!0;function S(e){if(!e)return{};const t=Object.assign({},e);return e.hasOwnProperty("floatOutput")&&(n.warnDeprecated("setting","floatOutput","precision"),t.precision=e.floatOutput?"single":"unsigned"),e.hasOwnProperty("outputToTexture")&&(n.warnDeprecated("setting","outputToTexture","pipeline"),t.pipeline=Boolean(e.outputToTexture)),e.hasOwnProperty("outputImmutable")&&(n.warnDeprecated("setting","outputImmutable","immutable"),t.immutable=Boolean(e.outputImmutable)),e.hasOwnProperty("floatTextures")&&(n.warnDeprecated("setting","floatTextures","optimizeFloatMemory"),t.optimizeFloatMemory=Boolean(e.floatTextures)),t}s.exports={GPU:class e{static disableValidation(){v=!1}static enableValidation(){v=!0}static get isGPUSupported(){return y.some(e=>e.isSupported)}static get isKernelMapSupported(){return y.some(e=>e.isSupported&&e.features.kernelMap)}static get isOffscreenCanvasSupported(){return"undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas||"undefined"!=typeof importScripts}static get isWebGLSupported(){return c.isSupported}static get isWebGL2Supported(){return h.isSupported}static get isHeadlessGLSupported(){return l.isSupported}static get isWebGPUSupported(){return d.isSupported}static isWebGPUAvailable(){return d.isSupported?navigator.gpu.requestAdapter().then(e=>null!==e,()=>!1):Promise.resolve(!1)}static get isWebAssemblySupported(){return f.isSupported}static get isCanvasSupported(){return"undefined"!=typeof HTMLCanvasElement}static get isGPUHTMLImageArraySupported(){return h.isSupported}static get isSinglePrecisionSupported(){return y.some(e=>e.isSupported&&e.features.isFloatRead&&e.features.isTextureFloat)}constructor(t){if(t=t||{},this.canvas=t.canvas||null,this.context=t.context||null,this.mode=t.mode,this.Kernel=null,this._webGPUDecision=null,"async"===t.mode&&(d.isSupported?e.isWebGPUAvailable().then(e=>{this._webGPUDecision=e},()=>{this._webGPUDecision=!1}):this._webGPUDecision=!1),this.kernels=[],this.pipelines=[],this.functions=[],this.nativeFunctions=[],this.injectedNative=null,"dev"!==this.mode){if(this.chooseKernel(),t.functions)for(let e=0;es.argumentTypes[e]));const l=this;function h(e){console.warn("Falling back to CPU"+(y.fallbackReason?`: ${y.fallbackReason}`:""));const s=new u(t,{argumentTypes:y.argumentTypes,constantTypes:y.constantTypes,graphical:y.graphical,loopMaxIterations:y.loopMaxIterations,constants:y.constants,dynamicOutput:y.dynamicOutput,dynamicArgument:y.dynamicArguments,output:y.output,precision:y.precision,pipeline:y.pipeline,immutable:y.immutable,optimizeFloatMemory:y.optimizeFloatMemory,fixIntegerDivisionAccuracy:y.fixIntegerDivisionAccuracy,functions:y.functions,nativeFunctions:y.nativeFunctions,injectedNative:y.injectedNative,subKernels:y.subKernels,strictIntegers:y.strictIntegers,randomSeed:y.randomSeed,debug:y.debug,asyncMode:y.asyncMode,onRequestFallback:h,onRequestSwitchKernel:c,canvas:y.graphical&&!y.context?y.canvas:null});s.fallbackReason=y.fallbackReason,s.build.apply(s,e);const r=s.run.apply(s,e);return y.replaceKernel(s),!l.canvas&&s.canvas&&(l.canvas=s.canvas),!l.context&&s.context&&(l.context=s.context),r}function c(e,s,r){r.debug&&console.warn("Switching kernels");let n=null;if(r.signature&&!a[r.signature]&&(a[r.signature]=r),r.dynamicOutput)for(let t=e.length-1;t>=0;t--){const s=e[t];"outputPrecisionMismatch"===s.type&&(n=s.needed)}const o=r.constructor,u=o.getArgumentTypes(r,s),l=o.getSignature(r,u),p=a[l];if(p)return p.onActivate(r),p;const d=a[l]=new o(t,{argumentTypes:u,constantTypes:r.constantTypes,graphical:r.graphical,loopMaxIterations:r.loopMaxIterations,constants:r.constants,dynamicOutput:r.dynamicOutput,dynamicArgument:r.dynamicArguments,context:r.context,canvas:r.canvas,output:n||r.output,precision:r.precision,pipeline:r.pipeline,immutable:r.immutable,optimizeFloatMemory:r.optimizeFloatMemory,fixIntegerDivisionAccuracy:r.fixIntegerDivisionAccuracy,functions:r.functions,nativeFunctions:r.nativeFunctions,injectedNative:r.injectedNative,subKernels:r.subKernels,strictIntegers:r.strictIntegers,randomSeed:r.randomSeed,debug:r.debug,asyncMode:r.asyncMode,gpu:r.gpu,validate:v,returnType:r.returnType,tactic:r.tactic,onRequestFallback:h,onRequestSwitchKernel:c,texture:r.texture,mappedTextures:r.mappedTextures,drawBuffersMap:r.drawBuffersMap});return d.build.apply(d,s),y.replaceKernel(d),i.push(d),d}const p=Object.assign({context:this.context,canvas:this.canvas,functions:this.functions,nativeFunctions:this.nativeFunctions,injectedNative:this.injectedNative,gpu:this,validate:v,onRequestFallback:h,onRequestSwitchKernel:c},o);"async"===this.mode&&(p.asyncMode=!0);let f,g=this.Kernel;"async"===this.mode&&o.graphical&&!0===this._webGPUDecision&&(g=d,p.canvas===this.canvas&&(p.canvas=o.canvas||null),p.context===this.context&&(p.context=o.context||null),p.asyncMode=!0);try{f=new g(t,p)}catch(e){if(g===this.Kernel)throw e;f=new this.Kernel(t,Object.assign({},p,{canvas:this.canvas,context:this.context}))}const y=m(f);if("async"===this.mode&&d.isSupported&&!(f instanceof d)){const s=this;f.onAsyncModeUpgrade=function(r,n){return e.isWebGPUAvailable().then(e=>{if(!e)return null;if(n.graphical)return n.debug&&console.warn("webgpu upgrade declined: graphical kernels keep their canvas"),null;let a;try{a=new d(t,{functions:n.functions,nativeFunctions:n.nativeFunctions,injectedNative:n.injectedNative,gpu:s,validate:v,asyncMode:!0,output:n.output,pipeline:n.pipeline,immutable:n.immutable,dynamicOutput:n.dynamicOutput,dynamicArguments:!0,loopMaxIterations:n.loopMaxIterations,constants:n.constants,constantTypes:n.constantTypes,argumentTypes:n.argumentTypes,precision:n.precision,tactic:n.tactic,strictIntegers:n.strictIntegers,fixIntegerDivisionAccuracy:n.fixIntegerDivisionAccuracy,subKernels:n.subKernels,graphical:n.graphical,debug:n.debug}),a.build.apply(a,r)}catch(e){return n.debug&&console.warn("webgpu upgrade declined: "+e.message),null}return a._buildPromise.then(()=>(i.push(a),a),e=>(n.debug&&console.warn("webgpu upgrade declined: "+e.message),a.destroy(),null))},()=>null)}}return this.canvas||(this.canvas=f.canvas),this.context||(this.context=f.context),i.push(f),y}createPipeline(e,t){if("function"!=typeof e)throw new Error("createPipeline requires an orchestration function");if("dev"===this.mode)throw new Error("createPipeline is not supported in dev mode");const s=new g(this,e,t);this.pipelines.push(s);const r=function(){return s.call(arguments)};return r.pipeline=s,r.setConstants=function(e){return s.setConstants(e),r},r.destroy=function(){return s.destroy()},Object.defineProperty(r,"executorKind",{get:()=>s.executorKind}),Object.defineProperty(r,"fallbackReason",{get:()=>s.fallbackReason}),Object.defineProperty(r,"plan",{get:()=>s.plan}),Object.defineProperty(r,"backend",{get:()=>{const e=s.executorKind;if("fused-sync"===e||"fused-threaded"===e)return"webasm";if("fused-encoder"===e)return"webgpu";const t=s.plan;if(!t)return null;for(const[e,s]of t.genericClones)if(0!==e.indexOf("up:"))return s.kernel.constructor.mode;return t.kernels.length>0?t.kernels[0].clone.kernel.constructor.mode:null}}),r}createKernelMap(){let e,t;const s=typeof arguments[arguments.length-2];if("function"===s||"string"===s?(e=arguments[arguments.length-2],t=arguments[arguments.length-1]):e=arguments[arguments.length-1],!("dev"===this.mode||this.Kernel.isSupported&&this.Kernel.features.kernelMap)){if("webgpu"===this.Kernel.mode)throw new Error("WebGPU backend does not yet support createKernelMap");if(this.mode&&x.indexOf(this.mode)<0&&"webasm"!==this.Kernel.mode)throw new Error(`kernelMap not supported on ${this.Kernel.name}`)}const r=S(t);if(t&&"object"==typeof t.argumentTypes&&(r.argumentTypes=Object.keys(t.argumentTypes).map(e=>t.argumentTypes[e])),Array.isArray(arguments[0])){r.subKernels=[];const e=arguments[0];for(let t=0;t0)throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.');return this.nativeFunctions.push(Object.assign({name:e,source:t},s)),this}injectNative(e){return this.injectedNative=e,this}destroy(){return new Promise((e,t)=>{this.kernels||e(),setTimeout(()=>{try{let s=Promise.resolve();if(this.pipelines){const e=this.pipelines.slice();s=Promise.all(e.map(e=>Promise.resolve(e.destroy()).catch(()=>{})))}const r=()=>{try{const e=this.kernels.slice();for(let t=0;t{const{utils:s}=i();t.exports={alias:function(e,t){const r=t.toString();return new Function(`return function ${e} (${s.getArgumentNamesFromString(r).join(", ")}) {\n ${s.getFunctionBodyFromString(r)}\n}`)()}}}),gt=e((e,t)=>{const{GPU:s}=ft(),{alias:c}=mt(),{utils:d}=i(),{Input:f,input:m}=r(),{Texture:g}=n(),{FunctionBuilder:y}=o(),{FunctionNode:x}=l(),{CPUFunctionNode:b}=h(),{CPUKernel:v}=p(),{HeadlessGLKernel:S}=ve(),{WebGLFunctionNode:T}=N(),{WebGLKernel:A}=be(),{kernelValueMaps:w}=xe(),{WebGL2FunctionNode:_}=Se(),{WebGL2Kernel:E}=tt(),{kernelValueMaps:I}=et(),{WGSLFunctionNode:k}=st(),{WebGPUKernel:C}=it(),{WebGPUContext:L}=rt(),{WebGPUBufferResult:D}=nt(),{WebAssemblyFunctionNode:F}=ot(),{WebAssemblyKernel:$}=lt(),{GLKernel:G}=R(),{Kernel:O}=a(),{FunctionTracer:V}=u();t.exports={alias:c,CPUFunctionNode:b,CPUKernel:v,GPU:s,FunctionBuilder:y,FunctionNode:x,HeadlessGLKernel:S,Input:f,input:m,Texture:g,utils:d,WebGL2FunctionNode:_,WebGL2Kernel:E,webGL2KernelValueMaps:I,WebGLFunctionNode:T,WebGLKernel:A,webGLKernelValueMaps:w,WGSLFunctionNode:k,WebGPUKernel:C,WebGPUContext:L,WebGPUBufferResult:D,WebAssemblyFunctionNode:F,WebAssemblyKernel:$,GLKernel:G,Kernel:O,FunctionTracer:V,plugins:{mathRandom:M()}}});return e((e,t)=>{const s=gt(),r=s.GPU;for(const e in s)s.hasOwnProperty(e)&&"GPU"!==e&&(r[e]=s[e]);function n(e){e.GPU&&e.GPU.prototype&&e.GPU.prototype.createKernel||Object.defineProperty(e,"GPU",{configurable:!0,get:()=>r,set(){}})}r.GPU=r,"undefined"!=typeof window&&n(window),"undefined"!=typeof self&&n(self),t.exports=r})()}); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):(e="undefined"!=typeof globalThis?globalThis:e||self).GPU=t()}(this,function(){var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),t=e((e,t)=>{function r(e){const t=new Array(e.length);for(let r=0;r{e.output=l(t),e.graphical&&u(e)},e.toJSON=()=>{throw new Error("Not usable with gpuMock")},e.setConstants=t=>(e.constants=t,e),e.setGraphical=t=>(e.graphical=t,e),e.setCanvas=t=>(e.canvas=t,e),e.setContext=t=>(e.context=t,e),e.destroy=()=>{},e.validateSettings=()=>{},e.graphical&&e.output&&u(e),e.exec=function(){return new Promise((t,r)=>{try{t(e.apply(e,arguments))}catch(e){r(e)}})},e.getPixels=t=>{const{x:r,y:s}=e.output;return t?function(e,t,r){const s=r/2|0,n=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee,r=["setWarnVarUsage","setArgumentTypes","setTactic","setOptimizeFloatMemory","setDebug","setLoopMaxIterations","setConstantTypes","setFunctions","setNativeFunctions","setInjectedNative","setPipeline","setPrecision","setOutputToTexture","setImmutable","setStrictIntegers","setDynamicOutput","setHardcodeConstants","setDynamicArguments","setUseLegacyEncoder","setWarnVarUsage","addSubKernel"];for(let s=0;s{var r,s;r=e,s=function(e){"use strict";var t=[509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,7,9,32,4,318,1,80,3,71,10,50,3,123,2,54,14,32,10,3,1,11,3,46,10,8,0,46,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,2,11,83,11,7,0,3,0,158,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,68,8,2,0,3,0,2,3,2,4,2,0,15,1,83,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,7,19,58,14,5,9,243,14,166,9,71,5,2,1,3,3,2,0,2,1,13,9,120,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,343,9,54,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,10,1,2,0,49,6,4,4,14,10,5350,0,7,14,11465,27,2343,9,87,9,39,4,60,6,26,9,535,9,470,0,2,54,8,3,82,0,12,1,19628,1,4178,9,519,45,3,22,543,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,101,0,161,6,10,9,357,0,62,13,499,13,245,1,2,9,726,6,110,6,6,9,4759,9,787719,239],r=[0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,13,10,2,14,2,6,2,1,2,10,2,14,2,6,2,1,4,51,13,310,10,21,11,7,25,5,2,41,2,8,70,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,39,27,10,22,251,41,7,1,17,2,60,28,11,0,9,21,43,17,47,20,28,22,13,52,58,1,3,0,14,44,33,24,27,35,30,0,3,0,9,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,20,1,64,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,31,9,2,0,3,0,2,37,2,0,26,0,2,0,45,52,19,3,21,2,31,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,38,6,186,43,117,63,32,7,3,0,3,7,2,1,2,23,16,0,2,0,95,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,19,72,200,32,32,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,16,0,2,12,2,33,125,0,80,921,103,110,18,195,2637,96,16,1071,18,5,26,3994,6,582,6842,29,1763,568,8,30,18,78,18,29,19,47,17,3,32,20,6,18,433,44,212,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,1237,42,9,8936,3,2,6,2,1,2,290,16,0,30,2,3,0,15,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,1845,30,7,5,262,61,147,44,11,6,17,0,322,29,19,43,485,27,229,29,3,0,496,6,2,3,2,1,2,14,2,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42719,33,4153,7,221,3,5761,15,7472,16,621,2467,541,1507,4938,6,4191],s="\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c8a\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7cd\ua7d0\ua7d1\ua7d3\ua7d5-\ua7dc\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc",n={3:"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",5:"class enum extends super const export import",6:"enum",strict:"implements interface let package private protected public static yield",strictBind:"eval arguments"},i="break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this",a={5:i,"5module":i+" export import",6:i+" const class extends export import super"},o=/^in(stanceof)?$/,u=new RegExp("["+s+"]"),l=new RegExp("["+s+"\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0897-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0cf3\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ece\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\u30fb\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f\uff65]");function h(e,t){for(var r=65536,s=0;se)return!1;if((r+=t[s+1])>=e)return!0}return!1}function c(e,t){return e<65?36===e:e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&u.test(String.fromCharCode(e)):!1!==t&&h(e,r)))}function p(e,s){return e<48?36===e:e<58||!(e<65)&&(e<91||(e<97?95===e:e<123||(e<=65535?e>=170&&l.test(String.fromCharCode(e)):!1!==s&&(h(e,r)||h(e,t)))))}var d=function(e,t){void 0===t&&(t={}),this.label=e,this.keyword=t.keyword,this.beforeExpr=!!t.beforeExpr,this.startsExpr=!!t.startsExpr,this.isLoop=!!t.isLoop,this.isAssign=!!t.isAssign,this.prefix=!!t.prefix,this.postfix=!!t.postfix,this.binop=t.binop||null,this.updateContext=null};function f(e,t){return new d(e,{beforeExpr:!0,binop:t})}var m={beforeExpr:!0},g={startsExpr:!0},y={};function x(e,t){return void 0===t&&(t={}),t.keyword=e,y[e]=new d(e,t)}var b={num:new d("num",g),regexp:new d("regexp",g),string:new d("string",g),name:new d("name",g),privateId:new d("privateId",g),eof:new d("eof"),bracketL:new d("[",{beforeExpr:!0,startsExpr:!0}),bracketR:new d("]"),braceL:new d("{",{beforeExpr:!0,startsExpr:!0}),braceR:new d("}"),parenL:new d("(",{beforeExpr:!0,startsExpr:!0}),parenR:new d(")"),comma:new d(",",m),semi:new d(";",m),colon:new d(":",m),dot:new d("."),question:new d("?",m),questionDot:new d("?."),arrow:new d("=>",m),template:new d("template"),invalidTemplate:new d("invalidTemplate"),ellipsis:new d("...",m),backQuote:new d("`",g),dollarBraceL:new d("${",{beforeExpr:!0,startsExpr:!0}),eq:new d("=",{beforeExpr:!0,isAssign:!0}),assign:new d("_=",{beforeExpr:!0,isAssign:!0}),incDec:new d("++/--",{prefix:!0,postfix:!0,startsExpr:!0}),prefix:new d("!/~",{beforeExpr:!0,prefix:!0,startsExpr:!0}),logicalOR:f("||",1),logicalAND:f("&&",2),bitwiseOR:f("|",3),bitwiseXOR:f("^",4),bitwiseAND:f("&",5),equality:f("==/!=/===/!==",6),relational:f("/<=/>=",7),bitShift:f("<>/>>>",8),plusMin:new d("+/-",{beforeExpr:!0,binop:9,prefix:!0,startsExpr:!0}),modulo:f("%",10),star:f("*",10),slash:f("/",10),starstar:new d("**",{beforeExpr:!0}),coalesce:f("??",1),_break:x("break"),_case:x("case",m),_catch:x("catch"),_continue:x("continue"),_debugger:x("debugger"),_default:x("default",m),_do:x("do",{isLoop:!0,beforeExpr:!0}),_else:x("else",m),_finally:x("finally"),_for:x("for",{isLoop:!0}),_function:x("function",g),_if:x("if"),_return:x("return",m),_switch:x("switch"),_throw:x("throw",m),_try:x("try"),_var:x("var"),_const:x("const"),_while:x("while",{isLoop:!0}),_with:x("with"),_new:x("new",{beforeExpr:!0,startsExpr:!0}),_this:x("this",g),_super:x("super",g),_class:x("class",g),_extends:x("extends",m),_export:x("export"),_import:x("import",g),_null:x("null",g),_true:x("true",g),_false:x("false",g),_in:x("in",{beforeExpr:!0,binop:7}),_instanceof:x("instanceof",{beforeExpr:!0,binop:7}),_typeof:x("typeof",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_void:x("void",{beforeExpr:!0,prefix:!0,startsExpr:!0}),_delete:x("delete",{beforeExpr:!0,prefix:!0,startsExpr:!0})},v=/\r\n?|\n|\u2028|\u2029/,S=new RegExp(v.source,"g");function T(e){return 10===e||13===e||8232===e||8233===e}function A(e,t,r){void 0===r&&(r=e.length);for(var s=t;s>10),56320+(1023&e)))}var R=/(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/,N=function(e,t){this.line=e,this.column=t};N.prototype.offset=function(e){return new N(this.line,this.column+e)};var M=function(e,t,r){this.start=t,this.end=r,null!==e.sourceFile&&(this.source=e.sourceFile)};function O(e,t){for(var r=1,s=0;;){var n=A(e,s,t);if(n<0)return new N(r,t-s);++r,s=n}}var G={ecmaVersion:null,sourceType:"script",onInsertedSemicolon:null,onTrailingComma:null,allowReserved:null,allowReturnOutsideFunction:!1,allowImportExportEverywhere:!1,allowAwaitOutsideFunction:null,allowSuperOutsideMethod:null,allowHashBang:!1,checkPrivateFields:!0,locations:!1,onToken:null,onComment:null,ranges:!1,program:null,sourceFile:null,directSourceFile:null,preserveParens:!1},V=!1;function P(e){var t={};for(var r in G)t[r]=e&&C(e,r)?e[r]:G[r];if("latest"===t.ecmaVersion?t.ecmaVersion=1e8:null==t.ecmaVersion?(!V&&"object"==typeof console&&console.warn&&(V=!0,console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.")),t.ecmaVersion=11):t.ecmaVersion>=2015&&(t.ecmaVersion-=2009),null==t.allowReserved&&(t.allowReserved=t.ecmaVersion<5),e&&null!=e.allowHashBang||(t.allowHashBang=t.ecmaVersion>=14),L(t.onToken)){var s=t.onToken;t.onToken=function(e){return s.push(e)}}return L(t.onComment)&&(t.onComment=function(e,t){return function(r,s,n,i,a,o){var u={type:r?"Block":"Line",value:s,start:n,end:i};e.locations&&(u.loc=new M(this,a,o)),e.ranges&&(u.range=[n,i]),t.push(u)}}(t,t.onComment)),t}var B=256;function z(e,t){return 2|(e?4:0)|(t?8:0)}var U=function(e,t,r){this.options=e=P(e),this.sourceFile=e.sourceFile,this.keywords=F(a[e.ecmaVersion>=6?6:"module"===e.sourceType?"5module":5]);var s="";!0!==e.allowReserved&&(s=n[e.ecmaVersion>=6?6:5===e.ecmaVersion?5:3],"module"===e.sourceType&&(s+=" await")),this.reservedWords=F(s);var i=(s?s+" ":"")+n.strict;this.reservedWordsStrict=F(i),this.reservedWordsStrictBind=F(i+" "+n.strictBind),this.input=String(t),this.containsEsc=!1,r?(this.pos=r,this.lineStart=this.input.lastIndexOf("\n",r-1)+1,this.curLine=this.input.slice(0,this.lineStart).split(v).length):(this.pos=this.lineStart=0,this.curLine=1),this.type=b.eof,this.value=null,this.start=this.end=this.pos,this.startLoc=this.endLoc=this.curPosition(),this.lastTokEndLoc=this.lastTokStartLoc=null,this.lastTokStart=this.lastTokEnd=this.pos,this.context=this.initialContext(),this.exprAllowed=!0,this.inModule="module"===e.sourceType,this.strict=this.inModule||this.strictDirective(this.pos),this.potentialArrowAt=-1,this.potentialArrowInForAwait=!1,this.yieldPos=this.awaitPos=this.awaitIdentPos=0,this.labels=[],this.undefinedExports=Object.create(null),0===this.pos&&e.allowHashBang&&"#!"===this.input.slice(0,2)&&this.skipLineComment(2),this.scopeStack=[],this.enterScope(1),this.regexpState=null,this.privateNameStack=[]},K={inFunction:{configurable:!0},inGenerator:{configurable:!0},inAsync:{configurable:!0},canAwait:{configurable:!0},allowSuper:{configurable:!0},allowDirectSuper:{configurable:!0},treatFunctionsAsVar:{configurable:!0},allowNewDotTarget:{configurable:!0},inClassStaticBlock:{configurable:!0}};U.prototype.parse=function(){var e=this.options.program||this.startNode();return this.nextToken(),this.parseTopLevel(e)},K.inFunction.get=function(){return(2&this.currentVarScope().flags)>0},K.inGenerator.get=function(){return(8&this.currentVarScope().flags)>0&&!this.currentVarScope().inClassFieldInit},K.inAsync.get=function(){return(4&this.currentVarScope().flags)>0&&!this.currentVarScope().inClassFieldInit},K.canAwait.get=function(){for(var e=this.scopeStack.length-1;e>=0;e--){var t=this.scopeStack[e];if(t.inClassFieldInit||t.flags&B)return!1;if(2&t.flags)return(4&t.flags)>0}return this.inModule&&this.options.ecmaVersion>=13||this.options.allowAwaitOutsideFunction},K.allowSuper.get=function(){var e=this.currentThisScope(),t=e.flags,r=e.inClassFieldInit;return(64&t)>0||r||this.options.allowSuperOutsideMethod},K.allowDirectSuper.get=function(){return(128&this.currentThisScope().flags)>0},K.treatFunctionsAsVar.get=function(){return this.treatFunctionsAsVarInScope(this.currentScope())},K.allowNewDotTarget.get=function(){var e=this.currentThisScope(),t=e.flags,r=e.inClassFieldInit;return(258&t)>0||r},K.inClassStaticBlock.get=function(){return(this.currentVarScope().flags&B)>0},U.extend=function(){for(var e=[],t=arguments.length;t--;)e[t]=arguments[t];for(var r=this,s=0;s=,?^&]/.test(n)||"!"===n&&"="===this.input.charAt(s+1))}e+=t[0].length,_.lastIndex=e,e+=_.exec(this.input)[0].length,";"===this.input[e]&&e++}},W.eat=function(e){return this.type===e&&(this.next(),!0)},W.isContextual=function(e){return this.type===b.name&&this.value===e&&!this.containsEsc},W.eatContextual=function(e){return!!this.isContextual(e)&&(this.next(),!0)},W.expectContextual=function(e){this.eatContextual(e)||this.unexpected()},W.canInsertSemicolon=function(){return this.type===b.eof||this.type===b.braceR||v.test(this.input.slice(this.lastTokEnd,this.start))},W.insertSemicolon=function(){if(this.canInsertSemicolon())return this.options.onInsertedSemicolon&&this.options.onInsertedSemicolon(this.lastTokEnd,this.lastTokEndLoc),!0},W.semicolon=function(){this.eat(b.semi)||this.insertSemicolon()||this.unexpected()},W.afterTrailingComma=function(e,t){if(this.type===e)return this.options.onTrailingComma&&this.options.onTrailingComma(this.lastTokStart,this.lastTokStartLoc),t||this.next(),!0},W.expect=function(e){this.eat(e)||this.unexpected()},W.unexpected=function(e){this.raise(null!=e?e:this.start,"Unexpected token")};var q=function(){this.shorthandAssign=this.trailingComma=this.parenthesizedAssign=this.parenthesizedBind=this.doubleProto=-1};W.checkPatternErrors=function(e,t){if(e){e.trailingComma>-1&&this.raiseRecoverable(e.trailingComma,"Comma is not permitted after the rest element");var r=t?e.parenthesizedAssign:e.parenthesizedBind;r>-1&&this.raiseRecoverable(r,t?"Assigning to rvalue":"Parenthesized pattern")}},W.checkExpressionErrors=function(e,t){if(!e)return!1;var r=e.shorthandAssign,s=e.doubleProto;if(!t)return r>=0||s>=0;r>=0&&this.raise(r,"Shorthand property assignments are valid only in destructuring patterns"),s>=0&&this.raiseRecoverable(s,"Redefinition of __proto__ property")},W.checkYieldAwaitInDefaultParams=function(){this.yieldPos&&(!this.awaitPos||this.yieldPos55295&&s<56320)return!0;if(c(s,!0)){for(var n=r+1;p(s=this.input.charCodeAt(n),!0);)++n;if(92===s||s>55295&&s<56320)return!0;var i=this.input.slice(r,n);if(!o.test(i))return!0}return!1},X.isAsyncFunction=function(){if(this.options.ecmaVersion<8||!this.isContextual("async"))return!1;_.lastIndex=this.pos;var e,t=_.exec(this.input),r=this.pos+t[0].length;return!(v.test(this.input.slice(this.pos,r))||"function"!==this.input.slice(r,r+8)||r+8!==this.input.length&&(p(e=this.input.charCodeAt(r+8))||e>55295&&e<56320))},X.parseStatement=function(e,t,r){var s,n=this.type,i=this.startNode();switch(this.isLet(e)&&(n=b._var,s="let"),n){case b._break:case b._continue:return this.parseBreakContinueStatement(i,n.keyword);case b._debugger:return this.parseDebuggerStatement(i);case b._do:return this.parseDoStatement(i);case b._for:return this.parseForStatement(i);case b._function:return e&&(this.strict||"if"!==e&&"label"!==e)&&this.options.ecmaVersion>=6&&this.unexpected(),this.parseFunctionStatement(i,!1,!e);case b._class:return e&&this.unexpected(),this.parseClass(i,!0);case b._if:return this.parseIfStatement(i);case b._return:return this.parseReturnStatement(i);case b._switch:return this.parseSwitchStatement(i);case b._throw:return this.parseThrowStatement(i);case b._try:return this.parseTryStatement(i);case b._const:case b._var:return s=s||this.value,e&&"var"!==s&&this.unexpected(),this.parseVarStatement(i,s);case b._while:return this.parseWhileStatement(i);case b._with:return this.parseWithStatement(i);case b.braceL:return this.parseBlock(!0,i);case b.semi:return this.parseEmptyStatement(i);case b._export:case b._import:if(this.options.ecmaVersion>10&&n===b._import){_.lastIndex=this.pos;var a=_.exec(this.input),o=this.pos+a[0].length,u=this.input.charCodeAt(o);if(40===u||46===u)return this.parseExpressionStatement(i,this.parseExpression())}return this.options.allowImportExportEverywhere||(t||this.raise(this.start,"'import' and 'export' may only appear at the top level"),this.inModule||this.raise(this.start,"'import' and 'export' may appear only with 'sourceType: module'")),n===b._import?this.parseImport(i):this.parseExport(i,r);default:if(this.isAsyncFunction())return e&&this.unexpected(),this.next(),this.parseFunctionStatement(i,!0,!e);var l=this.value,h=this.parseExpression();return n===b.name&&"Identifier"===h.type&&this.eat(b.colon)?this.parseLabeledStatement(i,l,h,e):this.parseExpressionStatement(i,h)}},X.parseBreakContinueStatement=function(e,t){var r="break"===t;this.next(),this.eat(b.semi)||this.insertSemicolon()?e.label=null:this.type!==b.name?this.unexpected():(e.label=this.parseIdent(),this.semicolon());for(var s=0;s=6?this.eat(b.semi):this.semicolon(),this.finishNode(e,"DoWhileStatement")},X.parseForStatement=function(e){this.next();var t=this.options.ecmaVersion>=9&&this.canAwait&&this.eatContextual("await")?this.lastTokStart:-1;if(this.labels.push(H),this.enterScope(0),this.expect(b.parenL),this.type===b.semi)return t>-1&&this.unexpected(t),this.parseFor(e,null);var r=this.isLet();if(this.type===b._var||this.type===b._const||r){var s=this.startNode(),n=r?"let":this.value;return this.next(),this.parseVar(s,!0,n),this.finishNode(s,"VariableDeclaration"),(this.type===b._in||this.options.ecmaVersion>=6&&this.isContextual("of"))&&1===s.declarations.length?(this.options.ecmaVersion>=9&&(this.type===b._in?t>-1&&this.unexpected(t):e.await=t>-1),this.parseForIn(e,s)):(t>-1&&this.unexpected(t),this.parseFor(e,s))}var i=this.isContextual("let"),a=!1,o=this.containsEsc,u=new q,l=this.start,h=t>-1?this.parseExprSubscripts(u,"await"):this.parseExpression(!0,u);return this.type===b._in||(a=this.options.ecmaVersion>=6&&this.isContextual("of"))?(t>-1?(this.type===b._in&&this.unexpected(t),e.await=!0):a&&this.options.ecmaVersion>=8&&(h.start!==l||o||"Identifier"!==h.type||"async"!==h.name?this.options.ecmaVersion>=9&&(e.await=!1):this.unexpected()),i&&a&&this.raise(h.start,"The left-hand side of a for-of loop may not start with 'let'."),this.toAssignable(h,!1,u),this.checkLValPattern(h),this.parseForIn(e,h)):(this.checkExpressionErrors(u,!0),t>-1&&this.unexpected(t),this.parseFor(e,h))},X.parseFunctionStatement=function(e,t,r){return this.next(),this.parseFunction(e,J|(r?0:Q),!1,t)},X.parseIfStatement=function(e){return this.next(),e.test=this.parseParenExpression(),e.consequent=this.parseStatement("if"),e.alternate=this.eat(b._else)?this.parseStatement("if"):null,this.finishNode(e,"IfStatement")},X.parseReturnStatement=function(e){return this.inFunction||this.options.allowReturnOutsideFunction||this.raise(this.start,"'return' outside of function"),this.next(),this.eat(b.semi)||this.insertSemicolon()?e.argument=null:(e.argument=this.parseExpression(),this.semicolon()),this.finishNode(e,"ReturnStatement")},X.parseSwitchStatement=function(e){var t;this.next(),e.discriminant=this.parseParenExpression(),e.cases=[],this.expect(b.braceL),this.labels.push(Y),this.enterScope(0);for(var r=!1;this.type!==b.braceR;)if(this.type===b._case||this.type===b._default){var s=this.type===b._case;t&&this.finishNode(t,"SwitchCase"),e.cases.push(t=this.startNode()),t.consequent=[],this.next(),s?t.test=this.parseExpression():(r&&this.raiseRecoverable(this.lastTokStart,"Multiple default clauses"),r=!0,t.test=null),this.expect(b.colon)}else t||this.unexpected(),t.consequent.push(this.parseStatement(null));return this.exitScope(),t&&this.finishNode(t,"SwitchCase"),this.next(),this.labels.pop(),this.finishNode(e,"SwitchStatement")},X.parseThrowStatement=function(e){return this.next(),v.test(this.input.slice(this.lastTokEnd,this.start))&&this.raise(this.lastTokEnd,"Illegal newline after throw"),e.argument=this.parseExpression(),this.semicolon(),this.finishNode(e,"ThrowStatement")};var Z=[];X.parseCatchClauseParam=function(){var e=this.parseBindingAtom(),t="Identifier"===e.type;return this.enterScope(t?32:0),this.checkLValPattern(e,t?4:2),this.expect(b.parenR),e},X.parseTryStatement=function(e){if(this.next(),e.block=this.parseBlock(),e.handler=null,this.type===b._catch){var t=this.startNode();this.next(),this.eat(b.parenL)?t.param=this.parseCatchClauseParam():(this.options.ecmaVersion<10&&this.unexpected(),t.param=null,this.enterScope(0)),t.body=this.parseBlock(!1),this.exitScope(),e.handler=this.finishNode(t,"CatchClause")}return e.finalizer=this.eat(b._finally)?this.parseBlock():null,e.handler||e.finalizer||this.raise(e.start,"Missing catch or finally clause"),this.finishNode(e,"TryStatement")},X.parseVarStatement=function(e,t,r){return this.next(),this.parseVar(e,!1,t,r),this.semicolon(),this.finishNode(e,"VariableDeclaration")},X.parseWhileStatement=function(e){return this.next(),e.test=this.parseParenExpression(),this.labels.push(H),e.body=this.parseStatement("while"),this.labels.pop(),this.finishNode(e,"WhileStatement")},X.parseWithStatement=function(e){return this.strict&&this.raise(this.start,"'with' in strict mode"),this.next(),e.object=this.parseParenExpression(),e.body=this.parseStatement("with"),this.finishNode(e,"WithStatement")},X.parseEmptyStatement=function(e){return this.next(),this.finishNode(e,"EmptyStatement")},X.parseLabeledStatement=function(e,t,r,s){for(var n=0,i=this.labels;n=0;o--){var u=this.labels[o];if(u.statementStart!==e.start)break;u.statementStart=this.start,u.kind=a}return this.labels.push({name:t,kind:a,statementStart:this.start}),e.body=this.parseStatement(s?-1===s.indexOf("label")?s+"label":s:"label"),this.labels.pop(),e.label=r,this.finishNode(e,"LabeledStatement")},X.parseExpressionStatement=function(e,t){return e.expression=t,this.semicolon(),this.finishNode(e,"ExpressionStatement")},X.parseBlock=function(e,t,r){for(void 0===e&&(e=!0),void 0===t&&(t=this.startNode()),t.body=[],this.expect(b.braceL),e&&this.enterScope(0);this.type!==b.braceR;){var s=this.parseStatement(null);t.body.push(s)}return r&&(this.strict=!1),this.next(),e&&this.exitScope(),this.finishNode(t,"BlockStatement")},X.parseFor=function(e,t){return e.init=t,this.expect(b.semi),e.test=this.type===b.semi?null:this.parseExpression(),this.expect(b.semi),e.update=this.type===b.parenR?null:this.parseExpression(),this.expect(b.parenR),e.body=this.parseStatement("for"),this.exitScope(),this.labels.pop(),this.finishNode(e,"ForStatement")},X.parseForIn=function(e,t){var r=this.type===b._in;return this.next(),"VariableDeclaration"===t.type&&null!=t.declarations[0].init&&(!r||this.options.ecmaVersion<8||this.strict||"var"!==t.kind||"Identifier"!==t.declarations[0].id.type)&&this.raise(t.start,(r?"for-in":"for-of")+" loop variable declaration may not have an initializer"),e.left=t,e.right=r?this.parseExpression():this.parseMaybeAssign(),this.expect(b.parenR),e.body=this.parseStatement("for"),this.exitScope(),this.labels.pop(),this.finishNode(e,r?"ForInStatement":"ForOfStatement")},X.parseVar=function(e,t,r,s){for(e.declarations=[],e.kind=r;;){var n=this.startNode();if(this.parseVarId(n,r),this.eat(b.eq)?n.init=this.parseMaybeAssign(t):s||"const"!==r||this.type===b._in||this.options.ecmaVersion>=6&&this.isContextual("of")?s||"Identifier"===n.id.type||t&&(this.type===b._in||this.isContextual("of"))?n.init=null:this.raise(this.lastTokEnd,"Complex binding patterns require an initialization value"):this.unexpected(),e.declarations.push(this.finishNode(n,"VariableDeclarator")),!this.eat(b.comma))break}return e},X.parseVarId=function(e,t){e.id=this.parseBindingAtom(),this.checkLValPattern(e.id,"var"===t?1:2,!1)};var J=1,Q=2;function ee(e,t){var r=t.key.name,s=e[r],n="true";return"MethodDefinition"!==t.type||"get"!==t.kind&&"set"!==t.kind||(n=(t.static?"s":"i")+t.kind),"iget"===s&&"iset"===n||"iset"===s&&"iget"===n||"sget"===s&&"sset"===n||"sset"===s&&"sget"===n?(e[r]="true",!1):!!s||(e[r]=n,!1)}function te(e,t){var r=e.computed,s=e.key;return!r&&("Identifier"===s.type&&s.name===t||"Literal"===s.type&&s.value===t)}X.parseFunction=function(e,t,r,s,n){this.initFunction(e),(this.options.ecmaVersion>=9||this.options.ecmaVersion>=6&&!s)&&(this.type===b.star&&t&Q&&this.unexpected(),e.generator=this.eat(b.star)),this.options.ecmaVersion>=8&&(e.async=!!s),t&J&&(e.id=4&t&&this.type!==b.name?null:this.parseIdent(),!e.id||t&Q||this.checkLValSimple(e.id,this.strict||e.generator||e.async?this.treatFunctionsAsVar?1:2:3));var i=this.yieldPos,a=this.awaitPos,o=this.awaitIdentPos;return this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,this.enterScope(z(e.async,e.generator)),t&J||(e.id=this.type===b.name?this.parseIdent():null),this.parseFunctionParams(e),this.parseFunctionBody(e,r,!1,n),this.yieldPos=i,this.awaitPos=a,this.awaitIdentPos=o,this.finishNode(e,t&J?"FunctionDeclaration":"FunctionExpression")},X.parseFunctionParams=function(e){this.expect(b.parenL),e.params=this.parseBindingList(b.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams()},X.parseClass=function(e,t){this.next();var r=this.strict;this.strict=!0,this.parseClassId(e,t),this.parseClassSuper(e);var s=this.enterClassBody(),n=this.startNode(),i=!1;for(n.body=[],this.expect(b.braceL);this.type!==b.braceR;){var a=this.parseClassElement(null!==e.superClass);a&&(n.body.push(a),"MethodDefinition"===a.type&&"constructor"===a.kind?(i&&this.raiseRecoverable(a.start,"Duplicate constructor in the same class"),i=!0):a.key&&"PrivateIdentifier"===a.key.type&&ee(s,a)&&this.raiseRecoverable(a.key.start,"Identifier '#"+a.key.name+"' has already been declared"))}return this.strict=r,this.next(),e.body=this.finishNode(n,"ClassBody"),this.exitClassBody(),this.finishNode(e,t?"ClassDeclaration":"ClassExpression")},X.parseClassElement=function(e){if(this.eat(b.semi))return null;var t=this.options.ecmaVersion,r=this.startNode(),s="",n=!1,i=!1,a="method",o=!1;if(this.eatContextual("static")){if(t>=13&&this.eat(b.braceL))return this.parseClassStaticBlock(r),r;this.isClassElementNameStart()||this.type===b.star?o=!0:s="static"}if(r.static=o,!s&&t>=8&&this.eatContextual("async")&&(!this.isClassElementNameStart()&&this.type!==b.star||this.canInsertSemicolon()?s="async":i=!0),!s&&(t>=9||!i)&&this.eat(b.star)&&(n=!0),!s&&!i&&!n){var u=this.value;(this.eatContextual("get")||this.eatContextual("set"))&&(this.isClassElementNameStart()?a=u:s=u)}if(s?(r.computed=!1,r.key=this.startNodeAt(this.lastTokStart,this.lastTokStartLoc),r.key.name=s,this.finishNode(r.key,"Identifier")):this.parseClassElementName(r),t<13||this.type===b.parenL||"method"!==a||n||i){var l=!r.static&&te(r,"constructor"),h=l&&e;l&&"method"!==a&&this.raise(r.key.start,"Constructor can't have get/set modifier"),r.kind=l?"constructor":a,this.parseClassMethod(r,n,i,h)}else this.parseClassField(r);return r},X.isClassElementNameStart=function(){return this.type===b.name||this.type===b.privateId||this.type===b.num||this.type===b.string||this.type===b.bracketL||this.type.keyword},X.parseClassElementName=function(e){this.type===b.privateId?("constructor"===this.value&&this.raise(this.start,"Classes can't have an element named '#constructor'"),e.computed=!1,e.key=this.parsePrivateIdent()):this.parsePropertyName(e)},X.parseClassMethod=function(e,t,r,s){var n=e.key;"constructor"===e.kind?(t&&this.raise(n.start,"Constructor can't be a generator"),r&&this.raise(n.start,"Constructor can't be an async method")):e.static&&te(e,"prototype")&&this.raise(n.start,"Classes may not have a static property named prototype");var i=e.value=this.parseMethod(t,r,s);return"get"===e.kind&&0!==i.params.length&&this.raiseRecoverable(i.start,"getter should have no params"),"set"===e.kind&&1!==i.params.length&&this.raiseRecoverable(i.start,"setter should have exactly one param"),"set"===e.kind&&"RestElement"===i.params[0].type&&this.raiseRecoverable(i.params[0].start,"Setter cannot use rest params"),this.finishNode(e,"MethodDefinition")},X.parseClassField=function(e){if(te(e,"constructor")?this.raise(e.key.start,"Classes can't have a field named 'constructor'"):e.static&&te(e,"prototype")&&this.raise(e.key.start,"Classes can't have a static field named 'prototype'"),this.eat(b.eq)){var t=this.currentThisScope(),r=t.inClassFieldInit;t.inClassFieldInit=!0,e.value=this.parseMaybeAssign(),t.inClassFieldInit=r}else e.value=null;return this.semicolon(),this.finishNode(e,"PropertyDefinition")},X.parseClassStaticBlock=function(e){e.body=[];var t=this.labels;for(this.labels=[],this.enterScope(320);this.type!==b.braceR;){var r=this.parseStatement(null);e.body.push(r)}return this.next(),this.exitScope(),this.labels=t,this.finishNode(e,"StaticBlock")},X.parseClassId=function(e,t){this.type===b.name?(e.id=this.parseIdent(),t&&this.checkLValSimple(e.id,2,!1)):(!0===t&&this.unexpected(),e.id=null)},X.parseClassSuper=function(e){e.superClass=this.eat(b._extends)?this.parseExprSubscripts(null,!1):null},X.enterClassBody=function(){var e={declared:Object.create(null),used:[]};return this.privateNameStack.push(e),e.declared},X.exitClassBody=function(){var e=this.privateNameStack.pop(),t=e.declared,r=e.used;if(this.options.checkPrivateFields)for(var s=this.privateNameStack.length,n=0===s?null:this.privateNameStack[s-1],i=0;i=11&&(this.eatContextual("as")?(e.exported=this.parseModuleExportName(),this.checkExport(t,e.exported,this.lastTokStart)):e.exported=null),this.expectContextual("from"),this.type!==b.string&&this.unexpected(),e.source=this.parseExprAtom(),this.options.ecmaVersion>=16&&(e.attributes=this.parseWithClause()),this.semicolon(),this.finishNode(e,"ExportAllDeclaration")},X.parseExport=function(e,t){if(this.next(),this.eat(b.star))return this.parseExportAllDeclaration(e,t);if(this.eat(b._default))return this.checkExport(t,"default",this.lastTokStart),e.declaration=this.parseExportDefaultDeclaration(),this.finishNode(e,"ExportDefaultDeclaration");if(this.shouldParseExportStatement())e.declaration=this.parseExportDeclaration(e),"VariableDeclaration"===e.declaration.type?this.checkVariableExport(t,e.declaration.declarations):this.checkExport(t,e.declaration.id,e.declaration.id.start),e.specifiers=[],e.source=null;else{if(e.declaration=null,e.specifiers=this.parseExportSpecifiers(t),this.eatContextual("from"))this.type!==b.string&&this.unexpected(),e.source=this.parseExprAtom(),this.options.ecmaVersion>=16&&(e.attributes=this.parseWithClause());else{for(var r=0,s=e.specifiers;r=16&&(e.attributes=this.parseWithClause()),this.semicolon(),this.finishNode(e,"ImportDeclaration")},X.parseImportSpecifier=function(){var e=this.startNode();return e.imported=this.parseModuleExportName(),this.eatContextual("as")?e.local=this.parseIdent():(this.checkUnreserved(e.imported),e.local=e.imported),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportSpecifier")},X.parseImportDefaultSpecifier=function(){var e=this.startNode();return e.local=this.parseIdent(),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportDefaultSpecifier")},X.parseImportNamespaceSpecifier=function(){var e=this.startNode();return this.next(),this.expectContextual("as"),e.local=this.parseIdent(),this.checkLValSimple(e.local,2),this.finishNode(e,"ImportNamespaceSpecifier")},X.parseImportSpecifiers=function(){var e=[],t=!0;if(this.type===b.name&&(e.push(this.parseImportDefaultSpecifier()),!this.eat(b.comma)))return e;if(this.type===b.star)return e.push(this.parseImportNamespaceSpecifier()),e;for(this.expect(b.braceL);!this.eat(b.braceR);){if(t)t=!1;else if(this.expect(b.comma),this.afterTrailingComma(b.braceR))break;e.push(this.parseImportSpecifier())}return e},X.parseWithClause=function(){var e=[];if(!this.eat(b._with))return e;this.expect(b.braceL);for(var t={},r=!0;!this.eat(b.braceR);){if(r)r=!1;else if(this.expect(b.comma),this.afterTrailingComma(b.braceR))break;var s=this.parseImportAttribute(),n="Identifier"===s.key.type?s.key.name:s.key.value;C(t,n)&&this.raiseRecoverable(s.key.start,"Duplicate attribute key '"+n+"'"),t[n]=!0,e.push(s)}return e},X.parseImportAttribute=function(){var e=this.startNode();return e.key=this.type===b.string?this.parseExprAtom():this.parseIdent("never"!==this.options.allowReserved),this.expect(b.colon),this.type!==b.string&&this.unexpected(),e.value=this.parseExprAtom(),this.finishNode(e,"ImportAttribute")},X.parseModuleExportName=function(){if(this.options.ecmaVersion>=13&&this.type===b.string){var e=this.parseLiteral(this.value);return R.test(e.value)&&this.raise(e.start,"An export name cannot include a lone surrogate."),e}return this.parseIdent(!0)},X.adaptDirectivePrologue=function(e){for(var t=0;t=5&&"ExpressionStatement"===e.type&&"Literal"===e.expression.type&&"string"==typeof e.expression.value&&('"'===this.input[e.start]||"'"===this.input[e.start])};var re=U.prototype;re.toAssignable=function(e,t,r){if(this.options.ecmaVersion>=6&&e)switch(e.type){case"Identifier":this.inAsync&&"await"===e.name&&this.raise(e.start,"Cannot use 'await' as identifier inside an async function");break;case"ObjectPattern":case"ArrayPattern":case"AssignmentPattern":case"RestElement":break;case"ObjectExpression":e.type="ObjectPattern",r&&this.checkPatternErrors(r,!0);for(var s=0,n=e.properties;s=8&&!o&&"async"===u.name&&!this.canInsertSemicolon()&&this.eat(b._function))return this.overrideContext(ne.f_expr),this.parseFunction(this.startNodeAt(i,a),0,!1,!0,t);if(n&&!this.canInsertSemicolon()){if(this.eat(b.arrow))return this.parseArrowExpression(this.startNodeAt(i,a),[u],!1,t);if(this.options.ecmaVersion>=8&&"async"===u.name&&this.type===b.name&&!o&&(!this.potentialArrowInForAwait||"of"!==this.value||this.containsEsc))return u=this.parseIdent(!1),!this.canInsertSemicolon()&&this.eat(b.arrow)||this.unexpected(),this.parseArrowExpression(this.startNodeAt(i,a),[u],!0,t)}return u;case b.regexp:var l=this.value;return(s=this.parseLiteral(l.value)).regex={pattern:l.pattern,flags:l.flags},s;case b.num:case b.string:return this.parseLiteral(this.value);case b._null:case b._true:case b._false:return(s=this.startNode()).value=this.type===b._null?null:this.type===b._true,s.raw=this.type.keyword,this.next(),this.finishNode(s,"Literal");case b.parenL:var h=this.start,c=this.parseParenAndDistinguishExpression(n,t);return e&&(e.parenthesizedAssign<0&&!this.isSimpleAssignTarget(c)&&(e.parenthesizedAssign=h),e.parenthesizedBind<0&&(e.parenthesizedBind=h)),c;case b.bracketL:return s=this.startNode(),this.next(),s.elements=this.parseExprList(b.bracketR,!0,!0,e),this.finishNode(s,"ArrayExpression");case b.braceL:return this.overrideContext(ne.b_expr),this.parseObj(!1,e);case b._function:return s=this.startNode(),this.next(),this.parseFunction(s,0);case b._class:return this.parseClass(this.startNode(),!1);case b._new:return this.parseNew();case b.backQuote:return this.parseTemplate();case b._import:return this.options.ecmaVersion>=11?this.parseExprImport(r):this.unexpected();default:return this.parseExprAtomDefault()}},ae.parseExprAtomDefault=function(){this.unexpected()},ae.parseExprImport=function(e){var t=this.startNode();if(this.containsEsc&&this.raiseRecoverable(this.start,"Escape sequence in keyword import"),this.next(),this.type===b.parenL&&!e)return this.parseDynamicImport(t);if(this.type===b.dot){var r=this.startNodeAt(t.start,t.loc&&t.loc.start);return r.name="import",t.meta=this.finishNode(r,"Identifier"),this.parseImportMeta(t)}this.unexpected()},ae.parseDynamicImport=function(e){if(this.next(),e.source=this.parseMaybeAssign(),this.options.ecmaVersion>=16)this.eat(b.parenR)?e.options=null:(this.expect(b.comma),this.afterTrailingComma(b.parenR)?e.options=null:(e.options=this.parseMaybeAssign(),this.eat(b.parenR)||(this.expect(b.comma),this.afterTrailingComma(b.parenR)||this.unexpected())));else if(!this.eat(b.parenR)){var t=this.start;this.eat(b.comma)&&this.eat(b.parenR)?this.raiseRecoverable(t,"Trailing comma is not allowed in import()"):this.unexpected(t)}return this.finishNode(e,"ImportExpression")},ae.parseImportMeta=function(e){this.next();var t=this.containsEsc;return e.property=this.parseIdent(!0),"meta"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for import is 'import.meta'"),t&&this.raiseRecoverable(e.start,"'import.meta' must not contain escaped characters"),"module"===this.options.sourceType||this.options.allowImportExportEverywhere||this.raiseRecoverable(e.start,"Cannot use 'import.meta' outside a module"),this.finishNode(e,"MetaProperty")},ae.parseLiteral=function(e){var t=this.startNode();return t.value=e,t.raw=this.input.slice(this.start,this.end),110===t.raw.charCodeAt(t.raw.length-1)&&(t.bigint=t.raw.slice(0,-1).replace(/_/g,"")),this.next(),this.finishNode(t,"Literal")},ae.parseParenExpression=function(){this.expect(b.parenL);var e=this.parseExpression();return this.expect(b.parenR),e},ae.shouldParseArrow=function(e){return!this.canInsertSemicolon()},ae.parseParenAndDistinguishExpression=function(e,t){var r,s=this.start,n=this.startLoc,i=this.options.ecmaVersion>=8;if(this.options.ecmaVersion>=6){this.next();var a,o=this.start,u=this.startLoc,l=[],h=!0,c=!1,p=new q,d=this.yieldPos,f=this.awaitPos;for(this.yieldPos=0,this.awaitPos=0;this.type!==b.parenR;){if(h?h=!1:this.expect(b.comma),i&&this.afterTrailingComma(b.parenR,!0)){c=!0;break}if(this.type===b.ellipsis){a=this.start,l.push(this.parseParenItem(this.parseRestBinding())),this.type===b.comma&&this.raiseRecoverable(this.start,"Comma is not permitted after the rest element");break}l.push(this.parseMaybeAssign(!1,p,this.parseParenItem))}var m=this.lastTokEnd,g=this.lastTokEndLoc;if(this.expect(b.parenR),e&&this.shouldParseArrow(l)&&this.eat(b.arrow))return this.checkPatternErrors(p,!1),this.checkYieldAwaitInDefaultParams(),this.yieldPos=d,this.awaitPos=f,this.parseParenArrowList(s,n,l,t);l.length&&!c||this.unexpected(this.lastTokStart),a&&this.unexpected(a),this.checkExpressionErrors(p,!0),this.yieldPos=d||this.yieldPos,this.awaitPos=f||this.awaitPos,l.length>1?((r=this.startNodeAt(o,u)).expressions=l,this.finishNodeAt(r,"SequenceExpression",m,g)):r=l[0]}else r=this.parseParenExpression();if(this.options.preserveParens){var y=this.startNodeAt(s,n);return y.expression=r,this.finishNode(y,"ParenthesizedExpression")}return r},ae.parseParenItem=function(e){return e},ae.parseParenArrowList=function(e,t,r,s){return this.parseArrowExpression(this.startNodeAt(e,t),r,!1,s)};var le=[];ae.parseNew=function(){this.containsEsc&&this.raiseRecoverable(this.start,"Escape sequence in keyword new");var e=this.startNode();if(this.next(),this.options.ecmaVersion>=6&&this.type===b.dot){var t=this.startNodeAt(e.start,e.loc&&e.loc.start);t.name="new",e.meta=this.finishNode(t,"Identifier"),this.next();var r=this.containsEsc;return e.property=this.parseIdent(!0),"target"!==e.property.name&&this.raiseRecoverable(e.property.start,"The only valid meta property for new is 'new.target'"),r&&this.raiseRecoverable(e.start,"'new.target' must not contain escaped characters"),this.allowNewDotTarget||this.raiseRecoverable(e.start,"'new.target' can only be used in functions and class static block"),this.finishNode(e,"MetaProperty")}var s=this.start,n=this.startLoc;return e.callee=this.parseSubscripts(this.parseExprAtom(null,!1,!0),s,n,!0,!1),this.eat(b.parenL)?e.arguments=this.parseExprList(b.parenR,this.options.ecmaVersion>=8,!1):e.arguments=le,this.finishNode(e,"NewExpression")},ae.parseTemplateElement=function(e){var t=e.isTagged,r=this.startNode();return this.type===b.invalidTemplate?(t||this.raiseRecoverable(this.start,"Bad escape sequence in untagged template literal"),r.value={raw:this.value.replace(/\r\n?/g,"\n"),cooked:null}):r.value={raw:this.input.slice(this.start,this.end).replace(/\r\n?/g,"\n"),cooked:this.value},this.next(),r.tail=this.type===b.backQuote,this.finishNode(r,"TemplateElement")},ae.parseTemplate=function(e){void 0===e&&(e={});var t=e.isTagged;void 0===t&&(t=!1);var r=this.startNode();this.next(),r.expressions=[];var s=this.parseTemplateElement({isTagged:t});for(r.quasis=[s];!s.tail;)this.type===b.eof&&this.raise(this.pos,"Unterminated template literal"),this.expect(b.dollarBraceL),r.expressions.push(this.parseExpression()),this.expect(b.braceR),r.quasis.push(s=this.parseTemplateElement({isTagged:t}));return this.next(),this.finishNode(r,"TemplateLiteral")},ae.isAsyncProp=function(e){return!e.computed&&"Identifier"===e.key.type&&"async"===e.key.name&&(this.type===b.name||this.type===b.num||this.type===b.string||this.type===b.bracketL||this.type.keyword||this.options.ecmaVersion>=9&&this.type===b.star)&&!v.test(this.input.slice(this.lastTokEnd,this.start))},ae.parseObj=function(e,t){var r=this.startNode(),s=!0,n={};for(r.properties=[],this.next();!this.eat(b.braceR);){if(s)s=!1;else if(this.expect(b.comma),this.options.ecmaVersion>=5&&this.afterTrailingComma(b.braceR))break;var i=this.parseProperty(e,t);e||this.checkPropClash(i,n,t),r.properties.push(i)}return this.finishNode(r,e?"ObjectPattern":"ObjectExpression")},ae.parseProperty=function(e,t){var r,s,n,i,a=this.startNode();if(this.options.ecmaVersion>=9&&this.eat(b.ellipsis))return e?(a.argument=this.parseIdent(!1),this.type===b.comma&&this.raiseRecoverable(this.start,"Comma is not permitted after the rest element"),this.finishNode(a,"RestElement")):(a.argument=this.parseMaybeAssign(!1,t),this.type===b.comma&&t&&t.trailingComma<0&&(t.trailingComma=this.start),this.finishNode(a,"SpreadElement"));this.options.ecmaVersion>=6&&(a.method=!1,a.shorthand=!1,(e||t)&&(n=this.start,i=this.startLoc),e||(r=this.eat(b.star)));var o=this.containsEsc;return this.parsePropertyName(a),!e&&!o&&this.options.ecmaVersion>=8&&!r&&this.isAsyncProp(a)?(s=!0,r=this.options.ecmaVersion>=9&&this.eat(b.star),this.parsePropertyName(a)):s=!1,this.parsePropertyValue(a,e,r,s,n,i,t,o),this.finishNode(a,"Property")},ae.parseGetterSetter=function(e){e.kind=e.key.name,this.parsePropertyName(e),e.value=this.parseMethod(!1);var t="get"===e.kind?0:1;if(e.value.params.length!==t){var r=e.value.start;"get"===e.kind?this.raiseRecoverable(r,"getter should have no params"):this.raiseRecoverable(r,"setter should have exactly one param")}else"set"===e.kind&&"RestElement"===e.value.params[0].type&&this.raiseRecoverable(e.value.params[0].start,"Setter cannot use rest params")},ae.parsePropertyValue=function(e,t,r,s,n,i,a,o){(r||s)&&this.type===b.colon&&this.unexpected(),this.eat(b.colon)?(e.value=t?this.parseMaybeDefault(this.start,this.startLoc):this.parseMaybeAssign(!1,a),e.kind="init"):this.options.ecmaVersion>=6&&this.type===b.parenL?(t&&this.unexpected(),e.kind="init",e.method=!0,e.value=this.parseMethod(r,s)):t||o||!(this.options.ecmaVersion>=5)||e.computed||"Identifier"!==e.key.type||"get"!==e.key.name&&"set"!==e.key.name||this.type===b.comma||this.type===b.braceR||this.type===b.eq?this.options.ecmaVersion>=6&&!e.computed&&"Identifier"===e.key.type?((r||s)&&this.unexpected(),this.checkUnreserved(e.key),"await"!==e.key.name||this.awaitIdentPos||(this.awaitIdentPos=n),e.kind="init",t?e.value=this.parseMaybeDefault(n,i,this.copyNode(e.key)):this.type===b.eq&&a?(a.shorthandAssign<0&&(a.shorthandAssign=this.start),e.value=this.parseMaybeDefault(n,i,this.copyNode(e.key))):e.value=this.copyNode(e.key),e.shorthand=!0):this.unexpected():((r||s)&&this.unexpected(),this.parseGetterSetter(e))},ae.parsePropertyName=function(e){if(this.options.ecmaVersion>=6){if(this.eat(b.bracketL))return e.computed=!0,e.key=this.parseMaybeAssign(),this.expect(b.bracketR),e.key;e.computed=!1}return e.key=this.type===b.num||this.type===b.string?this.parseExprAtom():this.parseIdent("never"!==this.options.allowReserved)},ae.initFunction=function(e){e.id=null,this.options.ecmaVersion>=6&&(e.generator=e.expression=!1),this.options.ecmaVersion>=8&&(e.async=!1)},ae.parseMethod=function(e,t,r){var s=this.startNode(),n=this.yieldPos,i=this.awaitPos,a=this.awaitIdentPos;return this.initFunction(s),this.options.ecmaVersion>=6&&(s.generator=e),this.options.ecmaVersion>=8&&(s.async=!!t),this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,this.enterScope(64|z(t,s.generator)|(r?128:0)),this.expect(b.parenL),s.params=this.parseBindingList(b.parenR,!1,this.options.ecmaVersion>=8),this.checkYieldAwaitInDefaultParams(),this.parseFunctionBody(s,!1,!0,!1),this.yieldPos=n,this.awaitPos=i,this.awaitIdentPos=a,this.finishNode(s,"FunctionExpression")},ae.parseArrowExpression=function(e,t,r,s){var n=this.yieldPos,i=this.awaitPos,a=this.awaitIdentPos;return this.enterScope(16|z(r,!1)),this.initFunction(e),this.options.ecmaVersion>=8&&(e.async=!!r),this.yieldPos=0,this.awaitPos=0,this.awaitIdentPos=0,e.params=this.toAssignableList(t,!0),this.parseFunctionBody(e,!0,!1,s),this.yieldPos=n,this.awaitPos=i,this.awaitIdentPos=a,this.finishNode(e,"ArrowFunctionExpression")},ae.parseFunctionBody=function(e,t,r,s){var n=t&&this.type!==b.braceL,i=this.strict,a=!1;if(n)e.body=this.parseMaybeAssign(s),e.expression=!0,this.checkParams(e,!1);else{var o=this.options.ecmaVersion>=7&&!this.isSimpleParamList(e.params);i&&!o||(a=this.strictDirective(this.end))&&o&&this.raiseRecoverable(e.start,"Illegal 'use strict' directive in function with non-simple parameter list");var u=this.labels;this.labels=[],a&&(this.strict=!0),this.checkParams(e,!i&&!a&&!t&&!r&&this.isSimpleParamList(e.params)),this.strict&&e.id&&this.checkLValSimple(e.id,5),e.body=this.parseBlock(!1,void 0,a&&!i),e.expression=!1,this.adaptDirectivePrologue(e.body.body),this.labels=u}this.exitScope()},ae.isSimpleParamList=function(e){for(var t=0,r=e;t-1||n.functions.indexOf(e)>-1||n.var.indexOf(e)>-1,n.lexical.push(e),this.inModule&&1&n.flags&&delete this.undefinedExports[e]}else if(4===t)this.currentScope().lexical.push(e);else if(3===t){var i=this.currentScope();s=this.treatFunctionsAsVar?i.lexical.indexOf(e)>-1:i.lexical.indexOf(e)>-1||i.var.indexOf(e)>-1,i.functions.push(e)}else for(var a=this.scopeStack.length-1;a>=0;--a){var o=this.scopeStack[a];if(o.lexical.indexOf(e)>-1&&!(32&o.flags&&o.lexical[0]===e)||!this.treatFunctionsAsVarInScope(o)&&o.functions.indexOf(e)>-1){s=!0;break}if(o.var.push(e),this.inModule&&1&o.flags&&delete this.undefinedExports[e],259&o.flags)break}s&&this.raiseRecoverable(r,"Identifier '"+e+"' has already been declared")},ce.checkLocalExport=function(e){-1===this.scopeStack[0].lexical.indexOf(e.name)&&-1===this.scopeStack[0].var.indexOf(e.name)&&(this.undefinedExports[e.name]=e)},ce.currentScope=function(){return this.scopeStack[this.scopeStack.length-1]},ce.currentVarScope=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e];if(259&t.flags)return t}},ce.currentThisScope=function(){for(var e=this.scopeStack.length-1;;e--){var t=this.scopeStack[e];if(259&t.flags&&!(16&t.flags))return t}};var de=function(e,t,r){this.type="",this.start=t,this.end=0,e.options.locations&&(this.loc=new M(e,r)),e.options.directSourceFile&&(this.sourceFile=e.options.directSourceFile),e.options.ranges&&(this.range=[t,0])},fe=U.prototype;function me(e,t,r,s){return e.type=t,e.end=r,this.options.locations&&(e.loc.end=s),this.options.ranges&&(e.range[1]=r),e}fe.startNode=function(){return new de(this,this.start,this.startLoc)},fe.startNodeAt=function(e,t){return new de(this,e,t)},fe.finishNode=function(e,t){return me.call(this,e,t,this.lastTokEnd,this.lastTokEndLoc)},fe.finishNodeAt=function(e,t,r,s){return me.call(this,e,t,r,s)},fe.copyNode=function(e){var t=new de(this,e.start,this.startLoc);for(var r in e)t[r]=e[r];return t};var ge="ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS",ye=ge+" Extended_Pictographic",xe=ye+" EBase EComp EMod EPres ExtPict",be={9:ge,10:ye,11:ye,12:xe,13:xe,14:xe},ve={9:"",10:"",11:"",12:"",13:"",14:"Basic_Emoji Emoji_Keycap_Sequence RGI_Emoji_Modifier_Sequence RGI_Emoji_Flag_Sequence RGI_Emoji_Tag_Sequence RGI_Emoji_ZWJ_Sequence RGI_Emoji"},Se="Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu",Te="Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb",Ae=Te+" Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd",we=Ae+" Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho",_e=we+" Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi",Ee=_e+" Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith",Ie={9:Te,10:Ae,11:we,12:_e,13:Ee,14:Ee+" Gara Garay Gukh Gurung_Khema Hrkt Katakana_Or_Hiragana Kawi Kirat_Rai Krai Nag_Mundari Nagm Ol_Onal Onao Sunu Sunuwar Todhri Todr Tulu_Tigalari Tutg Unknown Zzzz"},ke={};function Ce(e){var t=ke[e]={binary:F(be[e]+" "+Se),binaryOfStrings:F(ve[e]),nonBinary:{General_Category:F(Se),Script:F(Ie[e])}};t.nonBinary.Script_Extensions=t.nonBinary.Script,t.nonBinary.gc=t.nonBinary.General_Category,t.nonBinary.sc=t.nonBinary.Script,t.nonBinary.scx=t.nonBinary.Script_Extensions}for(var Le=0,De=[9,10,11,12,13,14];Le=6?"uy":"")+(e.options.ecmaVersion>=9?"s":"")+(e.options.ecmaVersion>=13?"d":"")+(e.options.ecmaVersion>=15?"v":""),this.unicodeProperties=ke[e.options.ecmaVersion>=14?14:e.options.ecmaVersion],this.source="",this.flags="",this.start=0,this.switchU=!1,this.switchV=!1,this.switchN=!1,this.pos=0,this.lastIntValue=0,this.lastStringValue="",this.lastAssertionIsQuantifiable=!1,this.numCapturingParens=0,this.maxBackReference=0,this.groupNames=Object.create(null),this.backReferenceNames=[],this.branchID=null};function Ne(e){return 105===e||109===e||115===e}function Me(e){return 36===e||e>=40&&e<=43||46===e||63===e||e>=91&&e<=94||e>=123&&e<=125}function Oe(e){return e>=65&&e<=90||e>=97&&e<=122}function Ge(e){return Oe(e)||95===e}function Ve(e){return Ge(e)||Pe(e)}function Pe(e){return e>=48&&e<=57}function Be(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}function ze(e){return e>=65&&e<=70?e-65+10:e>=97&&e<=102?e-97+10:e-48}function Ue(e){return e>=48&&e<=55}Re.prototype.reset=function(e,t,r){var s=-1!==r.indexOf("v"),n=-1!==r.indexOf("u");this.start=0|e,this.source=t+"",this.flags=r,s&&this.parser.options.ecmaVersion>=15?(this.switchU=!0,this.switchV=!0,this.switchN=!0):(this.switchU=n&&this.parser.options.ecmaVersion>=6,this.switchV=!1,this.switchN=n&&this.parser.options.ecmaVersion>=9)},Re.prototype.raise=function(e){this.parser.raiseRecoverable(this.start,"Invalid regular expression: /"+this.source+"/: "+e)},Re.prototype.at=function(e,t){void 0===t&&(t=!1);var r=this.source,s=r.length;if(e>=s)return-1;var n=r.charCodeAt(e);if(!t&&!this.switchU||n<=55295||n>=57344||e+1>=s)return n;var i=r.charCodeAt(e+1);return i>=56320&&i<=57343?(n<<10)+i-56613888:n},Re.prototype.nextIndex=function(e,t){void 0===t&&(t=!1);var r=this.source,s=r.length;if(e>=s)return s;var n,i=r.charCodeAt(e);return!t&&!this.switchU||i<=55295||i>=57344||e+1>=s||(n=r.charCodeAt(e+1))<56320||n>57343?e+1:e+2},Re.prototype.current=function(e){return void 0===e&&(e=!1),this.at(this.pos,e)},Re.prototype.lookahead=function(e){return void 0===e&&(e=!1),this.at(this.nextIndex(this.pos,e),e)},Re.prototype.advance=function(e){void 0===e&&(e=!1),this.pos=this.nextIndex(this.pos,e)},Re.prototype.eat=function(e,t){return void 0===t&&(t=!1),this.current(t)===e&&(this.advance(t),!0)},Re.prototype.eatChars=function(e,t){void 0===t&&(t=!1);for(var r=this.pos,s=0,n=e;s-1&&this.raise(e.start,"Duplicate regular expression flag"),"u"===a&&(s=!0),"v"===a&&(n=!0)}this.options.ecmaVersion>=15&&s&&n&&this.raise(e.start,"Invalid regular expression flag")},Fe.validateRegExpPattern=function(e){this.regexp_pattern(e),!e.switchN&&this.options.ecmaVersion>=9&&function(e){for(var t in e)return!0;return!1}(e.groupNames)&&(e.switchN=!0,this.regexp_pattern(e))},Fe.regexp_pattern=function(e){e.pos=0,e.lastIntValue=0,e.lastStringValue="",e.lastAssertionIsQuantifiable=!1,e.numCapturingParens=0,e.maxBackReference=0,e.groupNames=Object.create(null),e.backReferenceNames.length=0,e.branchID=null,this.regexp_disjunction(e),e.pos!==e.source.length&&(e.eat(41)&&e.raise("Unmatched ')'"),(e.eat(93)||e.eat(125))&&e.raise("Lone quantifier brackets")),e.maxBackReference>e.numCapturingParens&&e.raise("Invalid escape");for(var t=0,r=e.backReferenceNames;t=16;for(t&&(e.branchID=new $e(e.branchID,null)),this.regexp_alternative(e);e.eat(124);)t&&(e.branchID=e.branchID.sibling()),this.regexp_alternative(e);t&&(e.branchID=e.branchID.parent),this.regexp_eatQuantifier(e,!0)&&e.raise("Nothing to repeat"),e.eat(123)&&e.raise("Lone quantifier brackets")},Fe.regexp_alternative=function(e){for(;e.pos=9&&(r=e.eat(60)),e.eat(61)||e.eat(33))return this.regexp_disjunction(e),e.eat(41)||e.raise("Unterminated group"),e.lastAssertionIsQuantifiable=!r,!0}return e.pos=t,!1},Fe.regexp_eatQuantifier=function(e,t){return void 0===t&&(t=!1),!!this.regexp_eatQuantifierPrefix(e,t)&&(e.eat(63),!0)},Fe.regexp_eatQuantifierPrefix=function(e,t){return e.eat(42)||e.eat(43)||e.eat(63)||this.regexp_eatBracedQuantifier(e,t)},Fe.regexp_eatBracedQuantifier=function(e,t){var r=e.pos;if(e.eat(123)){var s=0,n=-1;if(this.regexp_eatDecimalDigits(e)&&(s=e.lastIntValue,e.eat(44)&&this.regexp_eatDecimalDigits(e)&&(n=e.lastIntValue),e.eat(125)))return-1!==n&&n=16){var r=this.regexp_eatModifiers(e),s=e.eat(45);if(r||s){for(var n=0;n-1&&e.raise("Duplicate regular expression modifiers")}if(s){var a=this.regexp_eatModifiers(e);r||a||58!==e.current()||e.raise("Invalid regular expression modifiers");for(var o=0;o-1||r.indexOf(u)>-1)&&e.raise("Duplicate regular expression modifiers")}}}}if(e.eat(58)){if(this.regexp_disjunction(e),e.eat(41))return!0;e.raise("Unterminated group")}}e.pos=t}return!1},Fe.regexp_eatCapturingGroup=function(e){if(e.eat(40)){if(this.options.ecmaVersion>=9?this.regexp_groupSpecifier(e):63===e.current()&&e.raise("Invalid group"),this.regexp_disjunction(e),e.eat(41))return e.numCapturingParens+=1,!0;e.raise("Unterminated group")}return!1},Fe.regexp_eatModifiers=function(e){for(var t="",r=0;-1!==(r=e.current())&&Ne(r);)t+=$(r),e.advance();return t},Fe.regexp_eatExtendedAtom=function(e){return e.eat(46)||this.regexp_eatReverseSolidusAtomEscape(e)||this.regexp_eatCharacterClass(e)||this.regexp_eatUncapturingGroup(e)||this.regexp_eatCapturingGroup(e)||this.regexp_eatInvalidBracedQuantifier(e)||this.regexp_eatExtendedPatternCharacter(e)},Fe.regexp_eatInvalidBracedQuantifier=function(e){return this.regexp_eatBracedQuantifier(e,!0)&&e.raise("Nothing to repeat"),!1},Fe.regexp_eatSyntaxCharacter=function(e){var t=e.current();return!!Me(t)&&(e.lastIntValue=t,e.advance(),!0)},Fe.regexp_eatPatternCharacters=function(e){for(var t=e.pos,r=0;-1!==(r=e.current())&&!Me(r);)e.advance();return e.pos!==t},Fe.regexp_eatExtendedPatternCharacter=function(e){var t=e.current();return!(-1===t||36===t||t>=40&&t<=43||46===t||63===t||91===t||94===t||124===t||(e.advance(),0))},Fe.regexp_groupSpecifier=function(e){if(e.eat(63)){this.regexp_eatGroupName(e)||e.raise("Invalid group");var t=this.options.ecmaVersion>=16,r=e.groupNames[e.lastStringValue];if(r)if(t)for(var s=0,n=r;s=11,s=e.current(r);return e.advance(r),92===s&&this.regexp_eatRegExpUnicodeEscapeSequence(e,r)&&(s=e.lastIntValue),function(e){return c(e,!0)||36===e||95===e}(s)?(e.lastIntValue=s,!0):(e.pos=t,!1)},Fe.regexp_eatRegExpIdentifierPart=function(e){var t=e.pos,r=this.options.ecmaVersion>=11,s=e.current(r);return e.advance(r),92===s&&this.regexp_eatRegExpUnicodeEscapeSequence(e,r)&&(s=e.lastIntValue),function(e){return p(e,!0)||36===e||95===e||8204===e||8205===e}(s)?(e.lastIntValue=s,!0):(e.pos=t,!1)},Fe.regexp_eatAtomEscape=function(e){return!!(this.regexp_eatBackReference(e)||this.regexp_eatCharacterClassEscape(e)||this.regexp_eatCharacterEscape(e)||e.switchN&&this.regexp_eatKGroupName(e))||(e.switchU&&(99===e.current()&&e.raise("Invalid unicode escape"),e.raise("Invalid escape")),!1)},Fe.regexp_eatBackReference=function(e){var t=e.pos;if(this.regexp_eatDecimalEscape(e)){var r=e.lastIntValue;if(e.switchU)return r>e.maxBackReference&&(e.maxBackReference=r),!0;if(r<=e.numCapturingParens)return!0;e.pos=t}return!1},Fe.regexp_eatKGroupName=function(e){if(e.eat(107)){if(this.regexp_eatGroupName(e))return e.backReferenceNames.push(e.lastStringValue),!0;e.raise("Invalid named reference")}return!1},Fe.regexp_eatCharacterEscape=function(e){return this.regexp_eatControlEscape(e)||this.regexp_eatCControlLetter(e)||this.regexp_eatZero(e)||this.regexp_eatHexEscapeSequence(e)||this.regexp_eatRegExpUnicodeEscapeSequence(e,!1)||!e.switchU&&this.regexp_eatLegacyOctalEscapeSequence(e)||this.regexp_eatIdentityEscape(e)},Fe.regexp_eatCControlLetter=function(e){var t=e.pos;if(e.eat(99)){if(this.regexp_eatControlLetter(e))return!0;e.pos=t}return!1},Fe.regexp_eatZero=function(e){return 48===e.current()&&!Pe(e.lookahead())&&(e.lastIntValue=0,e.advance(),!0)},Fe.regexp_eatControlEscape=function(e){var t=e.current();return 116===t?(e.lastIntValue=9,e.advance(),!0):110===t?(e.lastIntValue=10,e.advance(),!0):118===t?(e.lastIntValue=11,e.advance(),!0):102===t?(e.lastIntValue=12,e.advance(),!0):114===t&&(e.lastIntValue=13,e.advance(),!0)},Fe.regexp_eatControlLetter=function(e){var t=e.current();return!!Oe(t)&&(e.lastIntValue=t%32,e.advance(),!0)},Fe.regexp_eatRegExpUnicodeEscapeSequence=function(e,t){void 0===t&&(t=!1);var r,s=e.pos,n=t||e.switchU;if(e.eat(117)){if(this.regexp_eatFixedHexDigits(e,4)){var i=e.lastIntValue;if(n&&i>=55296&&i<=56319){var a=e.pos;if(e.eat(92)&&e.eat(117)&&this.regexp_eatFixedHexDigits(e,4)){var o=e.lastIntValue;if(o>=56320&&o<=57343)return e.lastIntValue=1024*(i-55296)+(o-56320)+65536,!0}e.pos=a,e.lastIntValue=i}return!0}if(n&&e.eat(123)&&this.regexp_eatHexDigits(e)&&e.eat(125)&&(r=e.lastIntValue)>=0&&r<=1114111)return!0;n&&e.raise("Invalid unicode escape"),e.pos=s}return!1},Fe.regexp_eatIdentityEscape=function(e){if(e.switchU)return!!this.regexp_eatSyntaxCharacter(e)||!!e.eat(47)&&(e.lastIntValue=47,!0);var t=e.current();return!(99===t||e.switchN&&107===t||(e.lastIntValue=t,e.advance(),0))},Fe.regexp_eatDecimalEscape=function(e){e.lastIntValue=0;var t=e.current();if(t>=49&&t<=57){do{e.lastIntValue=10*e.lastIntValue+(t-48),e.advance()}while((t=e.current())>=48&&t<=57);return!0}return!1},Fe.regexp_eatCharacterClassEscape=function(e){var t=e.current();if(function(e){return 100===e||68===e||115===e||83===e||119===e||87===e}(t))return e.lastIntValue=-1,e.advance(),1;var r=!1;if(e.switchU&&this.options.ecmaVersion>=9&&((r=80===t)||112===t)){var s;if(e.lastIntValue=-1,e.advance(),e.eat(123)&&(s=this.regexp_eatUnicodePropertyValueExpression(e))&&e.eat(125))return r&&2===s&&e.raise("Invalid property name"),s;e.raise("Invalid property name")}return 0},Fe.regexp_eatUnicodePropertyValueExpression=function(e){var t=e.pos;if(this.regexp_eatUnicodePropertyName(e)&&e.eat(61)){var r=e.lastStringValue;if(this.regexp_eatUnicodePropertyValue(e)){var s=e.lastStringValue;return this.regexp_validateUnicodePropertyNameAndValue(e,r,s),1}}if(e.pos=t,this.regexp_eatLoneUnicodePropertyNameOrValue(e)){var n=e.lastStringValue;return this.regexp_validateUnicodePropertyNameOrValue(e,n)}return 0},Fe.regexp_validateUnicodePropertyNameAndValue=function(e,t,r){C(e.unicodeProperties.nonBinary,t)||e.raise("Invalid property name"),e.unicodeProperties.nonBinary[t].test(r)||e.raise("Invalid property value")},Fe.regexp_validateUnicodePropertyNameOrValue=function(e,t){return e.unicodeProperties.binary.test(t)?1:e.switchV&&e.unicodeProperties.binaryOfStrings.test(t)?2:void e.raise("Invalid property name")},Fe.regexp_eatUnicodePropertyName=function(e){var t=0;for(e.lastStringValue="";Ge(t=e.current());)e.lastStringValue+=$(t),e.advance();return""!==e.lastStringValue},Fe.regexp_eatUnicodePropertyValue=function(e){var t=0;for(e.lastStringValue="";Ve(t=e.current());)e.lastStringValue+=$(t),e.advance();return""!==e.lastStringValue},Fe.regexp_eatLoneUnicodePropertyNameOrValue=function(e){return this.regexp_eatUnicodePropertyValue(e)},Fe.regexp_eatCharacterClass=function(e){if(e.eat(91)){var t=e.eat(94),r=this.regexp_classContents(e);return e.eat(93)||e.raise("Unterminated character class"),t&&2===r&&e.raise("Negated character class may contain strings"),!0}return!1},Fe.regexp_classContents=function(e){return 93===e.current()?1:e.switchV?this.regexp_classSetExpression(e):(this.regexp_nonEmptyClassRanges(e),1)},Fe.regexp_nonEmptyClassRanges=function(e){for(;this.regexp_eatClassAtom(e);){var t=e.lastIntValue;if(e.eat(45)&&this.regexp_eatClassAtom(e)){var r=e.lastIntValue;!e.switchU||-1!==t&&-1!==r||e.raise("Invalid character class"),-1!==t&&-1!==r&&t>r&&e.raise("Range out of order in character class")}}},Fe.regexp_eatClassAtom=function(e){var t=e.pos;if(e.eat(92)){if(this.regexp_eatClassEscape(e))return!0;if(e.switchU){var r=e.current();(99===r||Ue(r))&&e.raise("Invalid class escape"),e.raise("Invalid escape")}e.pos=t}var s=e.current();return 93!==s&&(e.lastIntValue=s,e.advance(),!0)},Fe.regexp_eatClassEscape=function(e){var t=e.pos;if(e.eat(98))return e.lastIntValue=8,!0;if(e.switchU&&e.eat(45))return e.lastIntValue=45,!0;if(!e.switchU&&e.eat(99)){if(this.regexp_eatClassControlLetter(e))return!0;e.pos=t}return this.regexp_eatCharacterClassEscape(e)||this.regexp_eatCharacterEscape(e)},Fe.regexp_classSetExpression=function(e){var t,r=1;if(this.regexp_eatClassSetRange(e));else if(t=this.regexp_eatClassSetOperand(e)){2===t&&(r=2);for(var s=e.pos;e.eatChars([38,38]);)38!==e.current()&&(t=this.regexp_eatClassSetOperand(e))?2!==t&&(r=1):e.raise("Invalid character in character class");if(s!==e.pos)return r;for(;e.eatChars([45,45]);)this.regexp_eatClassSetOperand(e)||e.raise("Invalid character in character class");if(s!==e.pos)return r}else e.raise("Invalid character in character class");for(;;)if(!this.regexp_eatClassSetRange(e)){if(!(t=this.regexp_eatClassSetOperand(e)))return r;2===t&&(r=2)}},Fe.regexp_eatClassSetRange=function(e){var t=e.pos;if(this.regexp_eatClassSetCharacter(e)){var r=e.lastIntValue;if(e.eat(45)&&this.regexp_eatClassSetCharacter(e)){var s=e.lastIntValue;return-1!==r&&-1!==s&&r>s&&e.raise("Range out of order in character class"),!0}e.pos=t}return!1},Fe.regexp_eatClassSetOperand=function(e){return this.regexp_eatClassSetCharacter(e)?1:this.regexp_eatClassStringDisjunction(e)||this.regexp_eatNestedClass(e)},Fe.regexp_eatNestedClass=function(e){var t=e.pos;if(e.eat(91)){var r=e.eat(94),s=this.regexp_classContents(e);if(e.eat(93))return r&&2===s&&e.raise("Negated character class may contain strings"),s;e.pos=t}if(e.eat(92)){var n=this.regexp_eatCharacterClassEscape(e);if(n)return n;e.pos=t}return null},Fe.regexp_eatClassStringDisjunction=function(e){var t=e.pos;if(e.eatChars([92,113])){if(e.eat(123)){var r=this.regexp_classStringDisjunctionContents(e);if(e.eat(125))return r}else e.raise("Invalid escape");e.pos=t}return null},Fe.regexp_classStringDisjunctionContents=function(e){for(var t=this.regexp_classString(e);e.eat(124);)2===this.regexp_classString(e)&&(t=2);return t},Fe.regexp_classString=function(e){for(var t=0;this.regexp_eatClassSetCharacter(e);)t++;return 1===t?1:2},Fe.regexp_eatClassSetCharacter=function(e){var t=e.pos;if(e.eat(92))return!(!this.regexp_eatCharacterEscape(e)&&!this.regexp_eatClassSetReservedPunctuator(e)&&(e.eat(98)?(e.lastIntValue=8,0):(e.pos=t,1)));var r=e.current();return!(r<0||r===e.lookahead()&&function(e){return 33===e||e>=35&&e<=38||e>=42&&e<=44||46===e||e>=58&&e<=64||94===e||96===e||126===e}(r)||function(e){return 40===e||41===e||45===e||47===e||e>=91&&e<=93||e>=123&&e<=125}(r)||(e.advance(),e.lastIntValue=r,0))},Fe.regexp_eatClassSetReservedPunctuator=function(e){var t=e.current();return!!function(e){return 33===e||35===e||37===e||38===e||44===e||45===e||e>=58&&e<=62||64===e||96===e||126===e}(t)&&(e.lastIntValue=t,e.advance(),!0)},Fe.regexp_eatClassControlLetter=function(e){var t=e.current();return!(!Pe(t)&&95!==t||(e.lastIntValue=t%32,e.advance(),0))},Fe.regexp_eatHexEscapeSequence=function(e){var t=e.pos;if(e.eat(120)){if(this.regexp_eatFixedHexDigits(e,2))return!0;e.switchU&&e.raise("Invalid escape"),e.pos=t}return!1},Fe.regexp_eatDecimalDigits=function(e){var t=e.pos,r=0;for(e.lastIntValue=0;Pe(r=e.current());)e.lastIntValue=10*e.lastIntValue+(r-48),e.advance();return e.pos!==t},Fe.regexp_eatHexDigits=function(e){var t=e.pos,r=0;for(e.lastIntValue=0;Be(r=e.current());)e.lastIntValue=16*e.lastIntValue+ze(r),e.advance();return e.pos!==t},Fe.regexp_eatLegacyOctalEscapeSequence=function(e){if(this.regexp_eatOctalDigit(e)){var t=e.lastIntValue;if(this.regexp_eatOctalDigit(e)){var r=e.lastIntValue;t<=3&&this.regexp_eatOctalDigit(e)?e.lastIntValue=64*t+8*r+e.lastIntValue:e.lastIntValue=8*t+r}else e.lastIntValue=t;return!0}return!1},Fe.regexp_eatOctalDigit=function(e){var t=e.current();return Ue(t)?(e.lastIntValue=t-48,e.advance(),!0):(e.lastIntValue=0,!1)},Fe.regexp_eatFixedHexDigits=function(e,t){var r=e.pos;e.lastIntValue=0;for(var s=0;s=this.input.length?this.finishToken(b.eof):e.override?e.override(this):void this.readToken(this.fullCharCodeAtPos())},We.readToken=function(e){return c(e,this.options.ecmaVersion>=6)||92===e?this.readWord():this.getTokenFromCode(e)},We.fullCharCodeAtPos=function(){var e=this.input.charCodeAt(this.pos);if(e<=55295||e>=56320)return e;var t=this.input.charCodeAt(this.pos+1);return t<=56319||t>=57344?e:(e<<10)+t-56613888},We.skipBlockComment=function(){var e=this.options.onComment&&this.curPosition(),t=this.pos,r=this.input.indexOf("*/",this.pos+=2);if(-1===r&&this.raise(this.pos-2,"Unterminated comment"),this.pos=r+2,this.options.locations)for(var s=void 0,n=t;(s=A(this.input,n,this.pos))>-1;)++this.curLine,n=this.lineStart=s;this.options.onComment&&this.options.onComment(!0,this.input.slice(t+2,r),t,this.pos,e,this.curPosition())},We.skipLineComment=function(e){for(var t=this.pos,r=this.options.onComment&&this.curPosition(),s=this.input.charCodeAt(this.pos+=e);this.pos8&&e<14||e>=5760&&w.test(String.fromCharCode(e))))break e;++this.pos}}},We.finishToken=function(e,t){this.end=this.pos,this.options.locations&&(this.endLoc=this.curPosition());var r=this.type;this.type=e,this.value=t,this.updateContext(r)},We.readToken_dot=function(){var e=this.input.charCodeAt(this.pos+1);if(e>=48&&e<=57)return this.readNumber(!0);var t=this.input.charCodeAt(this.pos+2);return this.options.ecmaVersion>=6&&46===e&&46===t?(this.pos+=3,this.finishToken(b.ellipsis)):(++this.pos,this.finishToken(b.dot))},We.readToken_slash=function(){var e=this.input.charCodeAt(this.pos+1);return this.exprAllowed?(++this.pos,this.readRegexp()):61===e?this.finishOp(b.assign,2):this.finishOp(b.slash,1)},We.readToken_mult_modulo_exp=function(e){var t=this.input.charCodeAt(this.pos+1),r=1,s=42===e?b.star:b.modulo;return this.options.ecmaVersion>=7&&42===e&&42===t&&(++r,s=b.starstar,t=this.input.charCodeAt(this.pos+2)),61===t?this.finishOp(b.assign,r+1):this.finishOp(s,r)},We.readToken_pipe_amp=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?this.options.ecmaVersion>=12&&61===this.input.charCodeAt(this.pos+2)?this.finishOp(b.assign,3):this.finishOp(124===e?b.logicalOR:b.logicalAND,2):61===t?this.finishOp(b.assign,2):this.finishOp(124===e?b.bitwiseOR:b.bitwiseAND,1)},We.readToken_caret=function(){return 61===this.input.charCodeAt(this.pos+1)?this.finishOp(b.assign,2):this.finishOp(b.bitwiseXOR,1)},We.readToken_plus_min=function(e){var t=this.input.charCodeAt(this.pos+1);return t===e?45!==t||this.inModule||62!==this.input.charCodeAt(this.pos+2)||0!==this.lastTokEnd&&!v.test(this.input.slice(this.lastTokEnd,this.pos))?this.finishOp(b.incDec,2):(this.skipLineComment(3),this.skipSpace(),this.nextToken()):61===t?this.finishOp(b.assign,2):this.finishOp(b.plusMin,1)},We.readToken_lt_gt=function(e){var t=this.input.charCodeAt(this.pos+1),r=1;return t===e?(r=62===e&&62===this.input.charCodeAt(this.pos+2)?3:2,61===this.input.charCodeAt(this.pos+r)?this.finishOp(b.assign,r+1):this.finishOp(b.bitShift,r)):33!==t||60!==e||this.inModule||45!==this.input.charCodeAt(this.pos+2)||45!==this.input.charCodeAt(this.pos+3)?(61===t&&(r=2),this.finishOp(b.relational,r)):(this.skipLineComment(4),this.skipSpace(),this.nextToken())},We.readToken_eq_excl=function(e){var t=this.input.charCodeAt(this.pos+1);return 61===t?this.finishOp(b.equality,61===this.input.charCodeAt(this.pos+2)?3:2):61===e&&62===t&&this.options.ecmaVersion>=6?(this.pos+=2,this.finishToken(b.arrow)):this.finishOp(61===e?b.eq:b.prefix,1)},We.readToken_question=function(){var e=this.options.ecmaVersion;if(e>=11){var t=this.input.charCodeAt(this.pos+1);if(46===t){var r=this.input.charCodeAt(this.pos+2);if(r<48||r>57)return this.finishOp(b.questionDot,2)}if(63===t)return e>=12&&61===this.input.charCodeAt(this.pos+2)?this.finishOp(b.assign,3):this.finishOp(b.coalesce,2)}return this.finishOp(b.question,1)},We.readToken_numberSign=function(){var e=35;if(this.options.ecmaVersion>=13&&(++this.pos,c(e=this.fullCharCodeAtPos(),!0)||92===e))return this.finishToken(b.privateId,this.readWord1());this.raise(this.pos,"Unexpected character '"+$(e)+"'")},We.getTokenFromCode=function(e){switch(e){case 46:return this.readToken_dot();case 40:return++this.pos,this.finishToken(b.parenL);case 41:return++this.pos,this.finishToken(b.parenR);case 59:return++this.pos,this.finishToken(b.semi);case 44:return++this.pos,this.finishToken(b.comma);case 91:return++this.pos,this.finishToken(b.bracketL);case 93:return++this.pos,this.finishToken(b.bracketR);case 123:return++this.pos,this.finishToken(b.braceL);case 125:return++this.pos,this.finishToken(b.braceR);case 58:return++this.pos,this.finishToken(b.colon);case 96:if(this.options.ecmaVersion<6)break;return++this.pos,this.finishToken(b.backQuote);case 48:var t=this.input.charCodeAt(this.pos+1);if(120===t||88===t)return this.readRadixNumber(16);if(this.options.ecmaVersion>=6){if(111===t||79===t)return this.readRadixNumber(8);if(98===t||66===t)return this.readRadixNumber(2)}case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return this.readNumber(!1);case 34:case 39:return this.readString(e);case 47:return this.readToken_slash();case 37:case 42:return this.readToken_mult_modulo_exp(e);case 124:case 38:return this.readToken_pipe_amp(e);case 94:return this.readToken_caret();case 43:case 45:return this.readToken_plus_min(e);case 60:case 62:return this.readToken_lt_gt(e);case 61:case 33:return this.readToken_eq_excl(e);case 63:return this.readToken_question();case 126:return this.finishOp(b.prefix,1);case 35:return this.readToken_numberSign()}this.raise(this.pos,"Unexpected character '"+$(e)+"'")},We.finishOp=function(e,t){var r=this.input.slice(this.pos,this.pos+t);return this.pos+=t,this.finishToken(e,r)},We.readRegexp=function(){for(var e,t,r=this.pos;;){this.pos>=this.input.length&&this.raise(r,"Unterminated regular expression");var s=this.input.charAt(this.pos);if(v.test(s)&&this.raise(r,"Unterminated regular expression"),e)e=!1;else{if("["===s)t=!0;else if("]"===s&&t)t=!1;else if("/"===s&&!t)break;e="\\"===s}++this.pos}var n=this.input.slice(r,this.pos);++this.pos;var i=this.pos,a=this.readWord1();this.containsEsc&&this.unexpected(i);var o=this.regexpState||(this.regexpState=new Re(this));o.reset(r,n,a),this.validateRegExpFlags(o),this.validateRegExpPattern(o);var u=null;try{u=new RegExp(n,a)}catch(e){}return this.finishToken(b.regexp,{pattern:n,flags:a,value:u})},We.readInt=function(e,t,r){for(var s=this.options.ecmaVersion>=12&&void 0===t,n=r&&48===this.input.charCodeAt(this.pos),i=this.pos,a=0,o=0,u=0,l=null==t?1/0:t;u=97?h-97+10:h>=65?h-65+10:h>=48&&h<=57?h-48:1/0)>=e)break;o=h,a=a*e+c}}return s&&95===o&&this.raiseRecoverable(this.pos-1,"Numeric separator is not allowed at the last of digits"),this.pos===i||null!=t&&this.pos-i!==t?null:a},We.readRadixNumber=function(e){var t=this.pos;this.pos+=2;var r=this.readInt(e);return null==r&&this.raise(this.start+2,"Expected number in radix "+e),this.options.ecmaVersion>=11&&110===this.input.charCodeAt(this.pos)?(r=je(this.input.slice(t,this.pos)),++this.pos):c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number"),this.finishToken(b.num,r)},We.readNumber=function(e){var t=this.pos;e||null!==this.readInt(10,void 0,!0)||this.raise(t,"Invalid number");var r=this.pos-t>=2&&48===this.input.charCodeAt(t);r&&this.strict&&this.raise(t,"Invalid number");var s=this.input.charCodeAt(this.pos);if(!r&&!e&&this.options.ecmaVersion>=11&&110===s){var n=je(this.input.slice(t,this.pos));return++this.pos,c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number"),this.finishToken(b.num,n)}r&&/[89]/.test(this.input.slice(t,this.pos))&&(r=!1),46!==s||r||(++this.pos,this.readInt(10),s=this.input.charCodeAt(this.pos)),69!==s&&101!==s||r||(43!==(s=this.input.charCodeAt(++this.pos))&&45!==s||++this.pos,null===this.readInt(10)&&this.raise(t,"Invalid number")),c(this.fullCharCodeAtPos())&&this.raise(this.pos,"Identifier directly after number");var i,a=(i=this.input.slice(t,this.pos),r?parseInt(i,8):parseFloat(i.replace(/_/g,"")));return this.finishToken(b.num,a)},We.readCodePoint=function(){var e;if(123===this.input.charCodeAt(this.pos)){this.options.ecmaVersion<6&&this.unexpected();var t=++this.pos;e=this.readHexChar(this.input.indexOf("}",this.pos)-this.pos),++this.pos,e>1114111&&this.invalidStringToken(t,"Code point out of bounds")}else e=this.readHexChar(4);return e},We.readString=function(e){for(var t="",r=++this.pos;;){this.pos>=this.input.length&&this.raise(this.start,"Unterminated string constant");var s=this.input.charCodeAt(this.pos);if(s===e)break;92===s?(t+=this.input.slice(r,this.pos),t+=this.readEscapedChar(!1),r=this.pos):8232===s||8233===s?(this.options.ecmaVersion<10&&this.raise(this.start,"Unterminated string constant"),++this.pos,this.options.locations&&(this.curLine++,this.lineStart=this.pos)):(T(s)&&this.raise(this.start,"Unterminated string constant"),++this.pos)}return t+=this.input.slice(r,this.pos++),this.finishToken(b.string,t)};var qe={};We.tryReadTemplateToken=function(){this.inTemplateElement=!0;try{this.readTmplToken()}catch(e){if(e!==qe)throw e;this.readInvalidTemplateToken()}this.inTemplateElement=!1},We.invalidStringToken=function(e,t){if(this.inTemplateElement&&this.options.ecmaVersion>=9)throw qe;this.raise(e,t)},We.readTmplToken=function(){for(var e="",t=this.pos;;){this.pos>=this.input.length&&this.raise(this.start,"Unterminated template");var r=this.input.charCodeAt(this.pos);if(96===r||36===r&&123===this.input.charCodeAt(this.pos+1))return this.pos!==this.start||this.type!==b.template&&this.type!==b.invalidTemplate?(e+=this.input.slice(t,this.pos),this.finishToken(b.template,e)):36===r?(this.pos+=2,this.finishToken(b.dollarBraceL)):(++this.pos,this.finishToken(b.backQuote));if(92===r)e+=this.input.slice(t,this.pos),e+=this.readEscapedChar(!0),t=this.pos;else if(T(r)){switch(e+=this.input.slice(t,this.pos),++this.pos,r){case 13:10===this.input.charCodeAt(this.pos)&&++this.pos;case 10:e+="\n";break;default:e+=String.fromCharCode(r)}this.options.locations&&(++this.curLine,this.lineStart=this.pos),t=this.pos}else++this.pos}},We.readInvalidTemplateToken=function(){for(;this.pos=48&&t<=55){var s=this.input.substr(this.pos-1,3).match(/^[0-7]+/)[0],n=parseInt(s,8);return n>255&&(s=s.slice(0,-1),n=parseInt(s,8)),this.pos+=s.length-1,t=this.input.charCodeAt(this.pos),"0"===s&&56!==t&&57!==t||!this.strict&&!e||this.invalidStringToken(this.pos-1-s.length,e?"Octal literal in template string":"Octal literal in strict mode"),String.fromCharCode(n)}return T(t)?(this.options.locations&&(this.lineStart=this.pos,++this.curLine),""):String.fromCharCode(t)}},We.readHexChar=function(e){var t=this.pos,r=this.readInt(16,e);return null===r&&this.invalidStringToken(t,"Bad character escape sequence"),r},We.readWord1=function(){this.containsEsc=!1;for(var e="",t=!0,r=this.pos,s=this.options.ecmaVersion>=6;this.pos{var r=class{constructor(e,t){this.value=e,Array.isArray(t)?this.size=t:(this.size=new Int32Array(3),t.z?this.size=new Int32Array([t.x,t.y,t.z]):t.y?this.size=new Int32Array([t.x,t.y]):this.size=new Int32Array([t.x]));const[r,s,n]=this.size;if(n){if(this.value.length!==r*s*n)throw new Error(`Input size ${this.value.length} does not match ${r} * ${s} * ${n} = ${s*r*n}`)}else if(s){if(this.value.length!==r*s)throw new Error(`Input size ${this.value.length} does not match ${r} * ${s} = ${s*r}`)}else if(this.value.length!==r)throw new Error(`Input size ${this.value.length} does not match ${r}`)}toArray(){const{utils:e}=i(),[t,r,s]=this.size;return s?e.erectMemoryOptimized3DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,r,s):r?e.erectMemoryOptimized2DFloat(this.value.subarray?this.value:new Float32Array(this.value),t,r):this.value}};t.exports={Input:r,input:function(e,t){return new r(e,t)}}}),n=e((e,t)=>{t.exports={Texture:class{constructor(e){const{texture:t,size:r,dimensions:s,output:n,context:i,type:a="NumberTexture",kernel:o,internalFormat:u,textureFormat:l}=e;if(!n)throw new Error('settings property "output" required.');if(!i)throw new Error('settings property "context" required.');if(!t)throw new Error('settings property "texture" required.');if(!o)throw new Error('settings property "kernel" required.');this.texture=t,t._refs?t._refs++:t._refs=1,this.size=r,this.dimensions=s,this.output=n,this.context=i,this.kernel=o,this.type=a,this._deleted=!1,this.internalFormat=u,this.textureFormat=l}toArray(){throw new Error(`Not implemented on ${this.constructor.name}`)}clone(){throw new Error(`Not implemented on ${this.constructor.name}`)}delete(){throw new Error(`Not implemented on ${this.constructor.name}`)}clear(){throw new Error(`Not implemented on ${this.constructor.name}`)}}}}),i=e((e,t)=>{const i=r(),{Input:a}=s(),{Texture:o}=n(),u=/function ([^(]*)/,l=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,h=/([^\s,]+)/g,c={systemEndianness:()=>m,getSystemEndianness(){const e=new ArrayBuffer(4),t=new Uint32Array(e),r=new Uint8Array(e);if(t[0]=3735928559,239===r[0])return"LE";if(222===r[0])return"BE";throw new Error("unknown endianness")},isFunction:e=>"function"==typeof e,isFunctionString:e=>"string"==typeof e&&"function"===e.slice(0,8).toLowerCase(),getFunctionNameFromString(e){const t=u.exec(e);return t&&0!==t.length?t[1].trim():null},getFunctionBodyFromString:e=>e.substring(e.indexOf("{")+1,e.lastIndexOf("}")),getArgumentNamesFromString(e){const t=e.replace(l,"");let r=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(h);return null===r&&(r=[]),r},clone(e){if(null===e||"object"!=typeof e||e.hasOwnProperty("isActiveClone"))return e;const t=e.constructor();for(let r in e)Object.prototype.hasOwnProperty.call(e,r)&&(e.isActiveClone=null,t[r]=c.clone(e[r]),delete e.isActiveClone);return t},isArray:e=>!isNaN(e.length),typeFitsValue(e,t){if("string"!=typeof e||null==t)return!0;if(t.type)return!0;switch(e){case"Input":return t instanceof a;case"Boolean":return"boolean"==typeof t;case"Number":case"Integer":case"Float":return"number"==typeof t}return-1!==e.indexOf("Texture")?Boolean(t.type):0!==e.indexOf("Array")||c.isArray(t)},getVariableType(e,t){if(c.isArray(e))return e.length>0&&"IMG"===e[0].nodeName?"HTMLImageArray":"Array";switch(e.constructor){case Boolean:return"Boolean";case Number:return t&&Number.isInteger(e)?"Integer":"Float";case o:return e.type;case a:return"Input"}if("nodeName"in e)switch(e.nodeName){case"IMG":case"CANVAS":return"HTMLImage";case"VIDEO":return"HTMLVideo"}else{if(e.hasOwnProperty("type"))return e.type;if("undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)return"OffscreenCanvas";if("undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap)return"ImageBitmap";if("undefined"!=typeof ImageData&&e instanceof ImageData)return"ImageData"}return"Unknown"},getKernelTextureSize(e,t){let[r,s,n]=t,i=(r||1)*(s||1)*(n||1);return e.optimizeFloatMemory&&"single"===e.precision&&(r=i=Math.ceil(i/4)),s>1&&r*s===i?new Int32Array([r,s]):c.closestSquareDimensions(i)},closestSquareDimensions(e){const t=Math.sqrt(e);let r=Math.ceil(t),s=Math.floor(t);for(;r*sMath.floor((e+t-1)/t)*t,getDimensions(e,t){let r;if(c.isArray(e)){const t=[];let s=e;for(;c.isArray(s);)t.push(s.length),s=s[0];r=t.reverse()}else if(e instanceof o)r=e.output;else{if(!(e instanceof a))throw new Error(`Unknown dimensions of ${e}`);r=e.size}if(t)for(r=Array.from(r);r.length<3;)r.push(1);return new Int32Array(r)},flatten2dArrayTo(e,t){let r=0;for(let s=0;se.length>0?e.join(";\n")+";\n":"\n",warnDeprecated(e,t,r){r?console.warn(`You are using a deprecated ${e} "${t}". It has been replaced with "${r}". Fixing, but please upgrade as it will soon be removed.`):console.warn(`You are using a deprecated ${e} "${t}". It has been removed. Fixing, but please upgrade as it will soon be removed.`)},flipPixels:(e,t,r)=>{const s=r/2|0,n=4*t,i=new Uint8ClampedArray(4*t),a=e.slice(0);for(let e=0;ee.subarray(0,t),erect2DPackedFloat:(e,t,r)=>{const s=new Array(r);for(let n=0;n{const n=new Array(s);for(let i=0;ie.subarray(0,t),erectMemoryOptimized2DFloat:(e,t,r)=>{const s=new Array(r);for(let n=0;n{const n=new Array(s);for(let i=0;i{const r=new Float32Array(t);let s=0;for(let n=0;n{const s=new Array(r);let n=0;for(let i=0;i{const n=new Array(s);let i=0;for(let a=0;a{const r=new Array(t),s=4*t;let n=0;for(let t=0;t{const s=new Array(r),n=4*t;for(let i=0;i{const n=4*t,i=new Array(s);for(let a=0;a{const r=new Array(t),s=4*t;let n=0;for(let t=0;t{const s=4*t,n=new Array(r);for(let i=0;i{const n=4*t,i=new Array(s);for(let a=0;a{const r=new Array(e),s=4*t;let n=0;for(let t=0;t{const s=4*t,n=new Array(r);for(let i=0;i{const n=4*t,i=new Array(s);for(let a=0;a{const{findDependency:r,thisLookup:s,doNotDefine:n}=t;let a=t.flattened;a||(a=t.flattened={});const o=i.parse(e,{ecmaVersion:2020}),u=[];let l=0;const h=function e(t){if(Array.isArray(t)){const r=[];for(let s=0;snull!==e);return n.length<1?"":`${t.kind} ${n.join(",")}`;case"VariableDeclarator":return t.init?t.init.object&&"ThisExpression"===t.init.object.type?s(t.init.property.name,!0)?`${t.id.name} = ${e(t.init)}`:null:`${t.id.name} = ${e(t.init)}`:t.id.name;case"CallExpression":if("subarray"===t.callee.property.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("gl"===t.callee.object.name||"context"===t.callee.object.name)return`${e(t.callee.object)}.${e(t.callee.property)}(${t.arguments.map(t=>e(t)).join(", ")})`;if("ThisExpression"===t.callee.object.type)return u.push(r("this",t.callee.property.name)),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;if(t.callee.object.name){const s=r(t.callee.object.name,t.callee.property.name);return null===s?`${t.callee.object.name}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`:(u.push(s),`${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`)}if("MemberExpression"===t.callee.object.type)return`${e(t.callee.object)}.${t.callee.property.name}(${t.arguments.map(t=>e(t)).join(", ")})`;throw new Error("unknown ast.callee");case"ReturnStatement":return`return ${e(t.argument)}`;case"BinaryExpression":return`(${e(t.left)}${t.operator}${e(t.right)})`;case"UnaryExpression":return t.prefix?`${t.operator} ${e(t.argument)}`:`${e(t.argument)} ${t.operator}`;case"ExpressionStatement":return`${e(t.expression)}`;case"SequenceExpression":return`(${e(t.expressions)})`;case"ArrowFunctionExpression":return`(${t.params.map(e).join(", ")}) => ${e(t.body)}`;case"Literal":return t.raw;case"Identifier":return t.name;case"MemberExpression":return"ThisExpression"===t.object.type?s(t.property.name):t.computed?`${e(t.object)}[${e(t.property)}]`:e(t.object)+"."+e(t.property);case"ThisExpression":return"this";case"NewExpression":return`new ${e(t.callee)}(${t.arguments.map(t=>e(t)).join(", ")})`;case"ForStatement":return`for (${e(t.init)};${e(t.test)};${e(t.update)}) ${e(t.body)}`;case"AssignmentExpression":return`${e(t.left)}${t.operator}${e(t.right)}`;case"UpdateExpression":return`${e(t.argument)}${t.operator}`;case"IfStatement":{const r=e(t.consequent);if(!t.alternate)return`if (${e(t.test)}) ${r}`;const s="BlockStatement"===t.consequent.type?"":";";return`if (${e(t.test)}) ${r}${s} else ${e(t.alternate)}`}case"ThrowStatement":return`throw ${e(t.argument)}`;case"ObjectPattern":return t.properties.map(e).join(", ");case"ArrayPattern":return t.elements.map(e).join(", ");case"DebuggerStatement":return"debugger;";case"ConditionalExpression":return`${e(t.test)}?${e(t.consequent)}:${e(t.alternate)}`;case"Property":if("init"===t.kind)return e(t.key)}throw new Error(`unhandled ast.type of ${t.type}`)}(o);if(u.length>0){const e=[];for(let r=0;r{if("VariableDeclaration"!==e.type)throw new Error('Ast is not of type "VariableDeclaration"');const t=[];for(let r=0;r{const r=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].r},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),s=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].g},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),n=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].b},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),i=e.createKernel(function(e){return 255*e[this.thread.y][this.thread.x].a},{output:[t.width,t.height],precision:"unsigned",argumentTypes:{a:"HTMLImage"}}),a=[r(t),s(t),n(t),i(t)];return a.rKernel=r,a.gKernel=s,a.bKernel=n,a.aKernel=i,a.gpu=e,a},splitRGBAToCanvases:(e,t,r,s)=>{const n=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(t.r/255,0,0,255)},{output:[r,s],graphical:!0,argumentTypes:{v:"Array2D(4)"}});n(t);const i=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,t.g/255,0,255)},{output:[r,s],graphical:!0,argumentTypes:{v:"Array2D(4)"}});i(t);const a=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(0,0,t.b/255,255)},{output:[r,s],graphical:!0,argumentTypes:{v:"Array2D(4)"}});a(t);const o=e.createKernel(function(e){const t=e[this.thread.y][this.thread.x];this.color(255,255,255,t.a/255)},{output:[r,s],graphical:!0,argumentTypes:{v:"Array2D(4)"}});return o(t),[n.canvas,i.canvas,a.canvas,o.canvas]},getMinifySafeName:e=>{try{const{init:t}=i.parse(`const value = ${e.toString()}`,{ecmaVersion:2020}).body[0].declarations[0];return t.body.name||t.body.body[0].argument.name}catch(e){throw new Error("Unrecognized function type. Please use `() => yourFunctionVariableHere` or function() { return yourFunctionVariableHere; }")}},sanitizeName:function(e){return p.test(e)&&(e=e.replace(p,"S_S")),d.test(e)?e=e.replace(d,"U_U"):f.test(e)&&(e=e.replace(f,"u_u")),e}},p=/\$/,d=/__/,f=/_/,m=c.getSystemEndianness();t.exports={utils:c}}),a=e((e,t)=>{const{utils:r}=i(),{Input:n}=s();t.exports={Kernel:class{static get isSupported(){throw new Error(`"isSupported" not implemented on ${this.name}`)}static isContextMatch(e){throw new Error(`"isContextMatch" not implemented on ${this.name}`)}static getFeatures(){throw new Error(`"getFeatures" not implemented on ${this.name}`)}static destroyContext(e){throw new Error(`"destroyContext" called on ${this.name}`)}static nativeFunctionArguments(){throw new Error(`"nativeFunctionArguments" called on ${this.name}`)}static nativeFunctionReturnType(){throw new Error(`"nativeFunctionReturnType" called on ${this.name}`)}static combineKernels(){throw new Error(`"combineKernels" called on ${this.name}`)}constructor(e,t){if("object"!=typeof e){if("string"!=typeof e)throw new Error("source not a string");if(!r.isFunctionString(e))throw new Error("source not a function string")}this.useLegacyEncoder=!1,this.fallbackRequested=!1,this.fallbackReason=null,this.onRequestFallback=null,this.onRequestSwitchKernel=null,this.argumentNames="string"==typeof e?r.getArgumentNamesFromString(e):null,this.argumentTypes=null,this.declaredArgumentTypes=null,this.argumentSizes=null,this.argumentBitRatios=null,this.kernelArguments=null,this.kernelConstants=null,this.forceUploadKernelConstants=null,this.source=e,this.output=null,this.debug=!1,this.graphical=!1,this.loopMaxIterations=0,this.constants=null,this.constantTypes=null,this.constantBitRatios=null,this.dynamicArguments=!1,this.dynamicOutput=!1,this.canvas=null,this.context=null,this.checkContext=null,this.gpu=null,this.functions=null,this.nativeFunctions=null,this.injectedNative=null,this.subKernels=null,this.validate=!0,this.immutable=!1,this.pipeline=!1,this.asyncMode=!1,this.precision=null,this.tactic=null,this.plugins=null,this.returnType=null,this.leadingReturnStatement=null,this.followingReturnStatement=null,this.optimizeFloatMemory=null,this.strictIntegers=!1,this.fixIntegerDivisionAccuracy=null,this._optimizerDisabled=!1,this._inliningDisabled=!1,this.localizeThreadCoordinates=!1,this.loopUnrollLimit=8,this.randomSeed=null,this.built=!1,this.signature=null,this.switchingKernels=null}mergeSettings(e){for(let t in e)if(e.hasOwnProperty(t)&&this.hasOwnProperty(t)){switch(t){case"argumentTypes":this.argumentTypes=e[t],e[t]&&(this.declaredArgumentTypes=Array.isArray(e[t])?e[t].slice():e[t]);continue;case"output":if(!Array.isArray(e.output)){this.setOutput(e.output);continue}break;case"functions":this.functions=[];for(let t=0;te.name):null,returnType:this.returnType}}}buildSignature(e){const t=this.constructor;this.signature=t.getSignature(this,t.getArgumentTypes(this,e))}static getArgumentTypes(e,t){const s=new Array(t.length);for(let n=0;nt.argumentTypes[e])||[];const i=Object.keys(t.argumentTypes);if(i.length>0&&e.length>0&&n.every(e=>void 0===e))throw new Error(`argumentTypes keys [${i.join(", ")}] match none of the function's parameters [${e.join(", ")}] \u2014 a bundler may have renamed them. Use the array form: argumentTypes: ['${i.map(e=>t.argumentTypes[e]).join("', '")}']`)}else n=t.argumentTypes||[];return{name:t.name||r.getFunctionNameFromString(s)||("function"==typeof e&&e.name?e.name:null),source:s,argumentTypes:n,returnType:t.returnType||null}}onActivate(e){}switchKernels(e){this.switchingKernels?this.switchingKernels.push(e):this.switchingKernels=[e]}resetSwitchingKernels(){const e=this.switchingKernels;return this.switchingKernels=null,e}checkArgumentTypes(e){if(!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let s=0;s{let r=1610612736;function s(e,t){return e.start=r++,e.end=r++,t&&t.loc&&(e.loc=t.loc),e}const n=["Number","Float","Integer"],i="@this",a=["value[]","value[][]","value[][][]","value[][][][]","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]"];var o=class{constructor(e,t,r){this.functionNode=e,this.ast=t,this.loopUnrollLimit="number"==typeof r.loopUnrollLimit?r.loopUnrollLimit:8,this.lookupInlineTarget=r.lookupInlineTarget||null,this.inlineTargets=new Map,this.inlineCount=0,this.mutatedNames=h(t.body),this.usedNames=function(e){const t=new Set;return u(e,e=>{"Identifier"===e.type&&t.add(e.name)}),t}(t),this.hoistCount=0}freshName(){let e;do{e="optHoist"+this.hoistCount++}while(this.usedNames.has(e));return this.usedNames.add(e),e}freshInlineName(e){let t;do{t=`optIn${this.inlineCount++}_${e}`}while(this.usedNames.has(t));return this.usedNames.add(t),t}inlineTarget(e){if(!this.lookupInlineTarget)return null;if(this.inlineTargets.has(e))return this.inlineTargets.get(e);let t=null;try{t=this.lookupInlineTarget(e)||null}catch(e){t=null}return this.inlineTargets.set(e,t),t}isImmutableArrayRoot(e){if(this.mutatedNames.has(e))return!1;const{argumentNames:t}=this.functionNode;return Boolean(t)&&t.indexOf(e)>-1}readElementType(e,t){const r=this.readRootType(e,t);if(!r)return null;try{return this.functionNode.getLookupType(r)}catch(e){return null}}readRootType(e,t){const{functionNode:r}=this;if(0===t.indexOf("this.constants.")){if(this.mutatedNames.has(i))return null;const s=function(e,t){let r=(t.match(/\[\]/g)||[]).length,s=e;for(;r-- >0;){if(!s||"MemberExpression"!==s.type)return null;s=s.object}return s&&s.property&&s.property.name?s.property.name:null}(e,t);if(!s)return null;const n=r.constantTypes?r.constantTypes[s]:null;return"Float"===n?"Number":n||null}const s=c(e);if(!s||"Identifier"!==s.type)return null;if(!this.isImmutableArrayRoot(s.name))return null;const n=r.argumentNames.indexOf(s.name);return(r.argumentTypes?r.argumentTypes[n]:null)||null}};function u(e,t){if(e&&"object"==typeof e)if(Array.isArray(e))for(let r=0;r{let r=e;for(;r&&"MemberExpression"===r.type;)r=r.object;r&&"Identifier"===r.type&&t.add(r.name),r&&"ThisExpression"===r.type&&t.add(i)};return u(e,e=>{switch(e.type){case"AssignmentExpression":r(e.left);break;case"UpdateExpression":r(e.argument);break;case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.add(e.id.name);break;case"FunctionDeclaration":case"FunctionExpression":case"ArrowFunctionExpression":e.id&&e.id.name&&t.add(e.id.name);for(let r=0;r0&&(r.splice(t,0,...s),t+=s.length)}}function d(e,t){switch(t.type){case"BlockStatement":return p(e,t),null;case"IfStatement":return f(e,t,"consequent"),f(e,t,"alternate"),null;case"SwitchStatement":for(let r=0;r":return s>r;case">=":return s>=r;case"!==":case"!=":return s!==r;default:return!1}}(t),i=[],a=new Set,o=new Map;for(let t=0;t0)for(let e=0;ea.has(e)))continue;const r=t.filter(e=>!a.has(e));t.length=0;for(let e=0;e0&&(t[r]=s({type:"BlockStatement",body:i.concat([n])},n))}function m(e,t){for(let r=0;r{if(e&&"object"==typeof e&&!t)if(Array.isArray(e))for(let t=0;t{const c=t[h];if(c&&"object"==typeof c)if(Array.isArray(c))for(let e=0;e{if(r||"MemberExpression"!==t.type)return;const s=e.functionNode.getVariableSignature(t);s&&-1!==a.indexOf(s)&&(!e.functionNode.readsFaultAtOneLevel&&(s.match(/\[\]/g)||[]).length<2||"Input"!==e.readRootType(t,s)&&(r=!0))}),r}function b(e){if(!e)return null;if("Literal"===e.type&&"number"==typeof e.value)return e.value;if("UnaryExpression"===e.type&&"-"===e.operator){const t=b(e.argument);return null===t?null:-t}return null}function v(e,t,r){if(!t||"object"!=typeof t)return!1;switch(t.type){case"Literal":case"ThisExpression":return!0;case"Identifier":return!r.has(t.name);case"UnaryExpression":return"delete"!==t.operator&&"typeof"!==t.operator&&v(e,t.argument,r);case"BinaryExpression":case"LogicalExpression":return v(e,t.left,r)&&v(e,t.right,r);case"ConditionalExpression":return v(e,t.test,r)&&v(e,t.consequent,r)&&v(e,t.alternate,r);case"MemberExpression":return function(e,t,r){const s=e.functionNode.getVariableSignature(t);if(!s)return!1;switch(s){case"this.thread.value":case"this.output.value":return!0;case"this.constants.value":return!e.mutatedNames.has(i);case"value.value":return e.functionNode.isAstMathVariable(t);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":{const s=c(t);return!(!s||"Identifier"!==s.type||!e.isImmutableArrayRoot(s.name))&&S(e,t,r)}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":return!e.mutatedNames.has(i)&&S(e,t,r);default:return!1}}(e,t,r);default:return!1}}function S(e,t,r){let s=t;for(;s&&"MemberExpression"===s.type;){if(s.computed&&!v(e,s.property,r))return!1;s=s.object}return!0}function T(e){if(!e||"object"!=typeof e)return null;switch(e.type){case"Literal":return`L${typeof e.value}:${e.value}`;case"ThisExpression":return"this";case"Identifier":return`#${e.name}`;case"MemberExpression":{const t=T(e.object),r=T(e.property);return null===t||null===r?null:`M${e.computed?"[":"."}(${t},${r})`}case"UnaryExpression":{const t=T(e.argument);return null===t?null:`U${e.operator}(${t})`}case"BinaryExpression":case"LogicalExpression":{const t=T(e.left),r=T(e.right);return null===t||null===r?null:`B${e.operator}(${t},${r})`}default:return null}}const A=6e3,w=2e4;function _(e,t){e.lookupInlineTarget&&(t.body=E(e,t.body))}function E(e,t){const r=[],n=t.slice();let i=0;for(;n.length>0;){if(++i>w)throw new Error("optimizer: inlining did not converge");const t=n.shift(),a=[],o=C(e,t,a);if(o.expanded>0){const e=o.consumed?s({type:"EmptyStatement"},t):t;n.unshift(...a,e);continue}I(e,t),r.push(t)}return r}function I(e,t){switch(t.type){case"BlockStatement":return void _(e,t);case"IfStatement":return t.consequent=k(e,t.consequent),void(t.alternate&&(t.alternate=k(e,t.alternate)));case"ForStatement":case"WhileStatement":case"DoWhileStatement":return void(t.body=k(e,t.body));case"SwitchStatement":for(let r=0;re.inlineTarget(t),sites:[],clean:!0},s=L(t);for(let e=0;e{"CallExpression"!==e.type?"AssignmentExpression"!==e.type&&"UpdateExpression"!==e.type||(t.clean=!1):N(e)||(t.clean=!1)})}function R(e){return e.callee&&"Identifier"===e.callee.type?e.callee.name:null}function N(e){const{callee:t}=e;return Boolean(t)&&"MemberExpression"===t.type&&!t.computed&&t.object&&"Identifier"===t.object.type&&"Math"===t.object.name&&t.property&&"random"!==t.property.name}function M(e,t,r){const{node:s,entry:n,parent:i,key:a}=t,o=new Map;for(let t=0;t{u.set(t,e.freshInlineName(t))});const l=B(V(e,n.body,o,u));if(!l)throw new Error("optimizer: helper body no longer reduces");for(let e=0;e=e.length)return null;const r=e[t];if("ReturnStatement"===r.type)return t===e.length-1&&r.argument?r.argument:null;if("IfStatement"!==r.type)return null;const n=K(r.consequent);if(null===n)return null;let i;if(r.alternate){if(t!==e.length-1)return null;i=K(r.alternate)}else i=z(e,t+1);if(null===i)return null;if(!j(n)||!j(i))return null;const a=U(n),o=U(i);return"unknown"!==a&&"unknown"!==o&&a!==o?null:s({type:"ConditionalExpression",test:r.test,consequent:n,alternate:i},r)}function U(e){if(!e)return"unknown";if("Literal"===e.type&&"number"==typeof e.value)return Number.isInteger(e.value)?"int":"float";if("BinaryExpression"===e.type&&"+-*/".indexOf(e.operator)>-1){const t=U(e.left),r=U(e.right);return"float"===t||"float"===r?"float":"unknown"===t||"unknown"===r||"/"===e.operator?"unknown":"int"}return"unknown"}function K(e){return e?z("BlockStatement"===e.type?e.body:[e],0):null}function W(e){let t=!1;return u(e,e=>{"ReturnStatement"===e.type&&(t=!0)}),t}function j(e){let t=!0;return u(e,e=>{"CallExpression"!==e.type||N(e)||(t=!1)}),t}function q(e,t,r,s,n){e.has(t)||e.set(t,{name:t,ast:r,kind:s,params:(r.params||[]).map(e=>"Identifier"===e.type?e.name:null),body:r.body.body,assignedParams:new Set,localNames:new Set,returnsValue:!1,inlinable:"helper"===s,recursive:!1,calls:[],sites:[],selfSize:0,expandedSize:0});const i=[];u(r.body,e=>{"FunctionDeclaration"===e.type&&e.id&&e.id.name&&i.push(e)});for(let t=0;t{t++}),t}(e.body);const r=new Set,s=new Set,n=new Set;let i=!1,a=!1;u(e.body,e=>{"CallExpression"===e.type&&e.callee&&"MemberExpression"===e.callee.type&&e.callee.object&&"Math"===e.callee.object.name&&e.callee.property&&"random"===e.callee.property.name&&(a=!0)});const o=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t-1||t.has(s)))return void(e.inlinable=!1);e.localNames=r;for(let t=0;t320&&(e.inlinable=!1)):e.inlinable=!1}function H(e,t,r){const s=new Set,n={candidates:t=>{const r=e.get(t);return r&&r.inlinable&&!r.recursive?r:null},sites:[],clean:!0},i=e=>{for(let t=0;t{if(!e||"string"!=typeof e.type)return;if("FunctionDeclaration"===e.type)return;n.clean=!0,n.sites=[];const r=L(e);for(let e=0;e{if("CallExpression"!==t.type||s.has(t))return;const n=R(t);n&&e.has(n)&&r.add(n)});for(let e=0;e320&&(t.inlinable=!1,r=!0);t=!0;let s=null,n=6e3;for(const t of e.values()){let r=0;for(let s=0;sn&&(n=r,s=t)}if(!s)break;let i=null;for(let t=0;ti.expandedSize||r.expandedSize===i.expandedSize&&r.name0))return null;if("ForStatement"!==t.type)return null;const r=function(e,t){const{init:r}=t;if(!r||"VariableDeclaration"!==r.type)return null;if(1!==r.declarations.length)return null;const s=r.declarations[0];if(!s.id||"Identifier"!==s.id.type)return null;const n=se(s.init);return null===n||"var"===r.kind&&function(e,t,r){let s=!1;const n=e=>{if(!s&&e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t=r)return null;u.push(l),l+=o}return u}(t,r,e.loopUnrollLimit);if(!n)return null;if(t.init&&"VariableDeclaration"===t.init.type&&"Literal"!==t.init.declarations[0].init.type){const t=e.functionNode.loopMaxIterations||1e3;if(n.length>t)return null}const i=t.body?"BlockStatement"===t.body.type?t.body.body:[t.body]:[];if(!function(e,t){let r=!0;const s=()=>{r=!1},n=(e,i,a)=>{if(r&&e&&"object"==typeof e)if(Array.isArray(e))for(let t=0;t{t++}),t}(i)*(n.length-1);void 0===e.unrollAdded&&(e.unrollAdded=0);if(e.unrollAdded+a>A)return null;e.unrollAdded+=a;const o=[];for(let a=0;aee<=t,">":(e,t)=>e>t,">=":(e,t)=>e>=t,"!==":(e,t)=>e!==t,"!=":(e,t)=>e!==t};function se(e){const t=b(e);return null!==t&&Number.isInteger(t)?t:null}function ne(e,t,r,s){const n=new Array(t.length);for(let i=0;i=0?r:s({type:"UnaryExpression",operator:"-",prefix:!0,argument:r},t)}(n,t);const i={},a="MemberExpression"===t.type&&!t.computed;for(const s in t)"start"!==s&&"end"!==s&&(i[s]="loc"!==s&&"range"!==s&&"parent"!==s?ie(e,t[s],a&&"property"===s?null:r,n):t[s]);return s(i,t)}t.exports={optimize:function(e,t,r){if(!t||!t.body||"BlockStatement"!==t.body.type)return t;const s=new o(e,t,r||{});return p(s,t.body),_(s,t.body),J(s,t.body),t},buildInlinePlan:function(e){const t=new Map,r=e.kernel||{},s=new Set(["Math","Infinity"]);if(r.constants)for(const e in r.constants)s.add(e);for(let t=0;t-1,o=Boolean(n.hasDeclaredTypes);q(t,r,i,n.isRootKernel?"root":n.isSubKernel||a||o?"subKernel":"helper",s)}for(const e of t.values())s.add(e.name);for(const e of t.values())X(e,s);let n=!0;for(;n;){n=!1;for(const e of t.values())if(!e.hasEffects)for(let r=0;r{if("CallExpression"!==t.type)return;const r=R(t);r&&e.has(r)&&s.add(r)}),t.set(r.name,s)}const r=new Map,s=[],n=i=>{if("done"!==r.get(i))if("open"!==r.get(i)){r.set(i,"open"),s.push(i);for(const e of t.get(i)||[])n(e);s.pop(),r.set(i,"done")}else for(let t=s.lastIndexOf(i);t1&&(e.inlinable=!1,e.sites=[]);return a},threadLocalName:function(e,t){if(!e.localizeThreadCoordinates)return null;if(e.optimizerDisabled||!e.isRootKernel)return null;const{output:r}=e;if(!r||!r.length)return null;switch(t){case"x":return"x";case"y":return r.length>1?"y":"0";case"z":return r.length>2?"z":"0";default:return null}}}}),u=e((e,t)=>{const{buildInlinePlan:r}=o();t.exports={FunctionBuilder:class e{static fromKernel(t,r,s){const{kernelArguments:n,kernelConstants:i,argumentNames:a,argumentSizes:o,argumentBitRatios:u,constants:l,constantBitRatios:h,debug:c,loopMaxIterations:p,nativeFunctions:d,output:f,optimizeFloatMemory:m,precision:g,plugins:y,source:x,subKernels:b,functions:v,leadingReturnStatement:S,followingReturnStatement:T,dynamicArguments:A,dynamicOutput:w,loopUnrollLimit:_,localizeThreadCoordinates:E}=t,I=Boolean(t._optimizerDisabled),k=Boolean(t._inliningDisabled),C=new Array(n.length),L={};for(let e=0;eq.needsArgumentType(e,t),F=(e,t,r)=>{q.assignArgumentType(e,t,r)},$=(e,t,r)=>q.lookupReturnType(e,t,r),R=e=>q.lookupFunctionArgumentTypes(e),N=(e,t)=>q.lookupFunctionArgumentName(e,t),M=(e,t)=>q.lookupFunctionArgumentBitRatio(e,t),O=(e,t,r,s)=>{q.assignArgumentType(e,t,r,s)},G=(e,t,r,s)=>{q.assignArgumentBitRatio(e,t,r,s)},V=(e,t,r)=>{q.trackFunctionCall(e,t,r)},P=k?null:e=>q.lookupInlineTarget(e),B=(e,t)=>{const s=[];for(let t=0;tnew r(e.source,{name:e.name||void 0,returnType:e.returnType,argumentTypes:e.argumentTypes,hasDeclaredTypes:Boolean(e.returnType)||(Array.isArray(e.argumentTypes)?e.argumentTypes.some(e=>Boolean(e)):Boolean(e.argumentTypes&&Object.keys(e.argumentTypes).length>0)),output:f,plugins:y,constants:l,constantTypes:L,constantBitRatios:h,optimizeFloatMemory:m,precision:g,lookupReturnType:$,lookupFunctionArgumentTypes:R,lookupFunctionArgumentName:N,lookupFunctionArgumentBitRatio:M,needsArgumentType:D,assignArgumentType:F,triggerImplyArgumentType:O,triggerImplyArgumentBitRatio:G,onFunctionCall:V,onNestedFunction:B,optimizerDisabled:I,loopUnrollLimit:_,localizeThreadCoordinates:E,lookupInlineTarget:P})));let j=null;b&&(j=b.map(e=>{const{name:t,source:s}=e;return new r(s,Object.assign({},z,{name:t,isSubKernel:!0,isRootKernel:!1}))}));const q=new e({kernel:t,rootNode:K,functionNodes:W,nativeFunctions:d,subKernelNodes:j});return q}constructor(e){if(e=e||{},this.kernel=e.kernel,this.rootNode=e.rootNode,this.functionNodes=e.functionNodes||[],this.subKernelNodes=e.subKernelNodes||[],this.nativeFunctions=e.nativeFunctions||[],this.functionMap={},this.nativeFunctionNames=[],this.lookupChain=[],this.functionNodeDependencies={},this.functionCalls={},this._inlinePlan=null,this.rootNode&&(this.functionMap.kernel=this.rootNode),this.functionNodes)for(let e=0;e-1){const r=t.indexOf(e);if(-1===r)t.push(e);else{const e=t.splice(r,1)[0];t.push(e)}return t}const r=this.functionMap[e];if(r){const s=t.indexOf(e);if(-1===s){t.push(e),r.toString();for(let e=0;e-1){t.push(this.nativeFunctions[n].source);continue}const i=this.functionMap[s];i&&t.push(i.toString())}return t}toJSON(){return this.traceFunctionCalls(this.rootNode.name).reverse().map(e=>{const t=this.nativeFunctions.indexOf(e);if(t>-1)return{name:e,source:this.nativeFunctions[t].source};if(this.functionMap[e])return this.functionMap[e].toJSON();throw new Error(`function ${e} not found`)})}fromJSON(e,t){this.functionMap={};for(let r=0;r0){const n=t.arguments;for(let t=0;t{const{utils:r}=i();function s(e){return e.length>0?e[e.length-1]:null}const n="trackIdentifiers",a="memberExpression",o="inForLoopInit";t.exports={FunctionTracer:class{constructor(e){this.runningContexts=[],this.functionContexts=[],this.contexts=[],this.functionCalls=[],this.declarations=[],this.identifiers=[],this.functions=[],this.returnStatements=[],this.trackedIdentifiers=null,this.states=[],this.newFunctionContext(),this.scan(e)}isState(e){return this.states[this.states.length-1]===e}hasState(e){return this.states.indexOf(e)>-1}pushState(e){this.states.push(e)}popState(e){if(!this.isState(e))throw new Error(`Cannot pop the non-active state "${e}"`);this.states.pop()}get currentFunctionContext(){return s(this.functionContexts)}get currentContext(){return s(this.runningContexts)}newFunctionContext(){const e={"@contextType":"function"};this.contexts.push(e),this.functionContexts.push(e)}newContext(e){const t=Object.assign({"@contextType":"const/let"},this.currentContext);this.contexts.push(t),this.runningContexts.push(t),e();const{currentFunctionContext:r}=this;for(const e in r)r.hasOwnProperty(e)&&!t.hasOwnProperty(e)&&(t[e]=r[e]);return this.runningContexts.pop(),t}useFunctionContext(e){const t=s(this.functionContexts);this.runningContexts.push(t),e(),this.runningContexts.pop()}getIdentifiers(e){const t=this.trackedIdentifiers=[];return this.pushState(n),e(),this.trackedIdentifiers=null,this.popState(n),t}getDeclaration(e){const{currentContext:t,currentFunctionContext:r,runningContexts:s}=this,n=t[e]||r[e]||null;if(!n&&t===r&&s.length>0){const t=s[s.length-2];if(t[e])return t[e]}return n}scan(e){if(e)if(Array.isArray(e))for(let t=0;t{this.scan(e.body)});break;case"BlockStatement":this.newContext(()=>{this.scan(e.body)});break;case"AssignmentExpression":case"LogicalExpression":case"BinaryExpression":this.scan(e.left),this.scan(e.right);break;case"UpdateExpression":if("++"===e.operator){const t=this.getDeclaration(e.argument.name);t&&(t.suggestedType="Integer")}this.scan(e.argument);break;case"UnaryExpression":this.scan(e.argument);break;case"VariableDeclaration":"var"===e.kind?this.useFunctionContext(()=>{e.declarations=r.normalizeDeclarations(e),this.scan(e.declarations)}):(e.declarations=r.normalizeDeclarations(e),this.scan(e.declarations));break;case"VariableDeclarator":{const{currentContext:t}=this,r=this.hasState(o),s={ast:e,context:t,name:e.id.name,origin:"declaration",inForLoopInit:r,inForLoopTest:null,assignable:t===this.currentFunctionContext||!r&&!t.hasOwnProperty(e.id.name),suggestedType:null,valueType:null,dependencies:null,isSafe:null};t[e.id.name]||(t[e.id.name]=s),this.declarations.push(s),this.scan(e.id),this.scan(e.init);break}case"FunctionExpression":case"FunctionDeclaration":0===this.runningContexts.length?this.scan(e.body):this.functions.push(e);break;case"IfStatement":this.scan(e.test),this.scan(e.consequent),e.alternate&&this.scan(e.alternate);break;case"ForStatement":{let t;const r=this.newContext(()=>{this.pushState(o),this.scan(e.init),this.popState(o),t=this.getIdentifiers(()=>{this.scan(e.test)}),this.scan(e.update),this.newContext(()=>{this.scan(e.body)})});if(t)for(const e in r)"@contextType"!==e&&t.indexOf(e)>-1&&(r[e].inForLoopTest=!0);break}case"DoWhileStatement":case"WhileStatement":this.newContext(()=>{this.scan(e.body),this.scan(e.test)});break;case"Identifier":this.isState(n)&&this.trackedIdentifiers.push(e.name),this.identifiers.push({context:this.currentContext,declaration:this.getDeclaration(e.name),ast:e});break;case"ReturnStatement":this.returnStatements.push(e),this.scan(e.argument);break;case"MemberExpression":this.pushState(a),this.scan(e.object),this.scan(e.property),this.popState(a);break;case"ExpressionStatement":this.scan(e.expression);break;case"SequenceExpression":this.scan(e.expressions);break;case"CallExpression":this.functionCalls.push({context:this.currentContext,ast:e}),this.scan(e.arguments);break;case"ArrayExpression":this.scan(e.elements);break;case"ConditionalExpression":this.scan(e.test),this.scan(e.alternate),this.scan(e.consequent);break;case"SwitchStatement":this.scan(e.discriminant),this.scan(e.cases);break;case"SwitchCase":this.scan(e.test),this.scan(e.consequent);break;case"ThisExpression":case"Literal":case"DebuggerStatement":case"EmptyStatement":case"BreakStatement":case"ContinueStatement":break;default:throw new Error(`unhandled type "${e.type}"`)}}}}}),h=e((e,t)=>{const s=r(),{utils:n}=i(),{FunctionTracer:a}=l(),{optimize:u}=o(),h=["E","PI","SQRT2","SQRT1_2","LN2","LN10","LOG2E","LOG10E"],c=["abs","acos","acosh","asin","asinh","atan","atan2","atanh","cbrt","ceil","clz32","cos","cosh","expm1","exp","floor","fround","imul","log","log2","log10","log1p","max","min","pow","random","round","sign","sin","sinh","sqrt","tan","tanh","trunc"],p=["value","value[]","value[][]","value[][][]","value[][][][]","value.value","value.thread.value","this.thread.value","this.output.value","this.constants.value","this.constants.value[]","this.constants.value[][]","this.constants.value[][][]","this.constants.value[][][][]","fn()[]","fn()[][]","fn()[][][]","[][]"];const d={Number:"Number",Float:"Float",Integer:"Integer",Array:"Number","Array(2)":"Number","Array(3)":"Number","Array(4)":"Number","Matrix(2)":"Number","Matrix(3)":"Number","Matrix(4)":"Number",Array2D:"Number",Array3D:"Number",Input:"Number",HTMLCanvas:"Array(4)",OffscreenCanvas:"Array(4)",HTMLImage:"Array(4)",ImageBitmap:"Array(4)",ImageData:"Array(4)",HTMLVideo:"Array(4)",HTMLImageArray:"Array(4)",NumberTexture:"Number",MemoryOptimizedNumberTexture:"Number","Array1D(2)":"Array(2)","Array1D(3)":"Array(3)","Array1D(4)":"Array(4)","Array2D(2)":"Array(2)","Array2D(3)":"Array(3)","Array2D(4)":"Array(4)","Array3D(2)":"Array(2)","Array3D(3)":"Array(3)","Array3D(4)":"Array(4)","ArrayTexture(1)":"Number","ArrayTexture(2)":"Array(2)","ArrayTexture(3)":"Array(3)","ArrayTexture(4)":"Array(4)"};let f=536870912;function m(e,t){return e.start=f++,e.end=f++,t&&t.loc&&(e.loc=t.loc),e}function g(e,t){return e&&e.body&&"BlockStatement"===e.body.type?(y(e.body,t),e):e}function y(e,t){e.body=x(e.body,t)}function x(e,t){const r=[];for(let s=0;s{if(!e||"object"!=typeof e||r)return e;if(Array.isArray(e))return e.map(s);switch(e.type){case"ContinueStatement":return e.label?(r=!0,e):m({type:"BlockStatement",body:[...w(t),e]},e);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionExpression":case"FunctionDeclaration":case"ArrowFunctionExpression":default:return e;case"IfStatement":return e.consequent=s(e.consequent),e.alternate&&(e.alternate=s(e.alternate)),e;case"BlockStatement":return e.body=e.body.map(s),e;case"SwitchStatement":for(let t=0;t0?(r.push(e),r):[e]}case"WhileStatement":case"DoWhileStatement":return e.body&&(e.body=v(e.body,t)),[e];case"SwitchStatement":for(let r=0;r0&&this.argumentTypes.length!==this.argumentNames.length)throw new Error(`argumentTypes count of ${this.argumentTypes.length} exceeds ${this.argumentNames.length}`);if(this.output.length<1)throw new Error("this.output is not big enough")}isIdentifierConstant(e){return!!this.constants&&this.constants.hasOwnProperty(e)}isInput(e){return"Input"===this.argumentTypes[this.argumentNames.indexOf(e)]}pushState(e){this.states.push(e)}popState(e){if(this.state!==e)throw new Error(`Cannot popState ${e} when in ${this.state}`);this.states.pop()}isState(e){return this.state===e}get state(){return this.states[this.states.length-1]}astMemberExpressionUnroll(e){if("Identifier"===e.type)return e.name;if("ThisExpression"===e.type)return"this";if("MemberExpression"===e.type&&e.object&&e.property)return e.object.hasOwnProperty("name")&&"Math"!==e.object.name?this.astMemberExpressionUnroll(e.property):this.astMemberExpressionUnroll(e.object)+"."+this.astMemberExpressionUnroll(e.property);if(e.hasOwnProperty("expressions")){const t=e.expressions[0];if("Literal"===t.type&&0===t.value&&2===e.expressions.length)return this.astMemberExpressionUnroll(e.expressions[1])}throw this.astErrorOutput("Unknown astMemberExpressionUnroll",e)}get requiresSequenceFreeForInit(){return!1}get readsCanFault(){return!1}get readsFaultAtOneLevel(){return!1}getRawAST(e){if(this._rawAST)return this._rawAST;if("object"==typeof this.source)return g(this.source,this.requiresSequenceFreeForInit),this._rawAST=this.source;if(null===(e=e||s))throw new Error("Missing JS to AST parser");const t=Object.freeze(e.parse(`const parser_${this.name} = ${this.source};`,{locations:!0,ecmaVersion:2020})).body[0].declarations[0].init;return g(t,this.requiresSequenceFreeForInit),this._rawAST=t}getJsAST(e){if(this.ast)return this.ast;const t=this.getRawAST(e);try{this.optimizeAST(t)}catch(e){throw e&&"object"==typeof e&&(e.isOptimizerFailure=!0),e}return this.traceFunctionAST(t),this.ast=t}optimizeAST(e){return this.optimizerDisabled?e:u(this,e,{loopUnrollLimit:this.loopUnrollLimit,lookupInlineTarget:this.lookupInlineTarget})}getAssignedArguments(){if(this._assignedArguments)return this._assignedArguments;const e=new Set,t=new Set,r=this.argumentNames||[],s=n=>{if(n&&"object"==typeof n)if(Array.isArray(n))for(const e of n)s(e);else{"AssignmentExpression"===n.type&&"Identifier"===n.left.type&&-1!==r.indexOf(n.left.name)&&e.add(n.left.name),"UpdateExpression"===n.type&&"Identifier"===n.argument.type&&-1!==r.indexOf(n.argument.name)&&e.add(n.argument.name),"VariableDeclarator"===n.type&&"Identifier"===n.id.type&&-1!==r.indexOf(n.id.name)&&t.add(n.id.name);for(const e in n){if("loc"===e||"range"===e||"parent"===e)continue;const t=n[e];t&&"object"==typeof t&&s(t)}}};s(this.getJsAST());for(const r of t)e.delete(r);return this._assignedArguments=e}traceFunctionAST(e){const{contexts:t,declarations:r,functions:s,identifiers:n,functionCalls:i}=new a(e);this.contexts=t,this.identifiers=n,this.functionCalls=i,this.functions=s;for(let e=0;e":case"<":return"Boolean";case"&":case"|":case"^":case"<<":case">>":case">>>":return"Integer"}const r=this.getType(e.left);if(this.isState("skip-literal-correction"))return r;if("LiteralInteger"===r){const t=this.getType(e.right);return"LiteralInteger"===t?e.left.value%1==0?"Integer":"Float":t}if("Integer"===r){const t=this.getType(e.right);if("Number"===t||"Float"===t)return t}return d[r]||r;case"UpdateExpression":case"ReturnStatement":return this.getType(e.argument);case"UnaryExpression":return"~"===e.operator?"Integer":this.getType(e.argument);case"VariableDeclaration":{const t=e.declarations;let r;for(let e=0;ee.isSafe)}getDependencies(e,t,r){if(t||(t=[]),!e)return null;if(Array.isArray(e)){for(let s=0;s-1/0&&e.value<1/0&&!isNaN(e.value))});break;case"VariableDeclarator":return this.getDependencies(e.init,t,r);case"Identifier":const s=this.getDeclaration(e);if(s)t.push({name:e.name,origin:"declaration",isSafe:!r&&this.isSafeDependencies(s.dependencies)});else if(this.argumentNames.indexOf(e.name)>-1)t.push({name:e.name,origin:"argument",isSafe:!1});else if(this.strictTypingChecking)throw new Error(`Cannot find identifier origin "${e.name}"`);break;case"FunctionDeclaration":return this.getDependencies(e.body.body[e.body.body.length-1],t,r);case"ReturnStatement":return this.getDependencies(e.argument,t);case"BinaryExpression":case"LogicalExpression":return r="/"===e.operator||"*"===e.operator,this.getDependencies(e.left,t,r),this.getDependencies(e.right,t,r),t;case"UnaryExpression":case"UpdateExpression":return this.getDependencies(e.argument,t,r);case"VariableDeclaration":return this.getDependencies(e.declarations,t,r);case"ArrayExpression":return t.push({origin:"declaration",isSafe:!0}),t;case"CallExpression":return t.push({origin:"function",isSafe:!0}),t;case"MemberExpression":const n=this.getMemberExpressionDetails(e);switch(n.signature){case"value[]":this.getDependencies(e.object,t,r);break;case"value[][]":this.getDependencies(e.object.object,t,r);break;case"value[][][]":this.getDependencies(e.object.object.object,t,r);break;case"this.output.value":this.dynamicOutput&&t.push({name:n.name,origin:"output",isSafe:!1})}if(n)return n.property&&this.getDependencies(n.property,t,r),n.xProperty&&this.getDependencies(n.xProperty,t,r),n.yProperty&&this.getDependencies(n.yProperty,t,r),n.zProperty&&this.getDependencies(n.zProperty,t,r),t;case"SequenceExpression":return this.getDependencies(e.expressions,t,r);default:throw this.astErrorOutput(`Unhandled type ${e.type} in getDependencies`,e)}return t}getVariableSignature(e,t){if(!this.isAstVariable(e))throw new Error(`ast of type "${e.type}" is not a variable signature`);if("Identifier"===e.type)return"value";const r=[];for(;e;)e.computed?r.push("[]"):"ThisExpression"===e.type?r.unshift("this"):e.property&&e.property.name?"x"===e.property.name||"y"===e.property.name||"z"===e.property.name?r.unshift(t?"."+e.property.name:".value"):"constants"===e.property.name||"thread"===e.property.name||"output"===e.property.name?r.unshift("."+e.property.name):r.unshift(t?"."+e.property.name:".value"):e.name?r.unshift(t?e.name:"value"):e.callee&&e.callee.name?r.unshift(t?e.callee.name+"()":"fn()"):e.elements?r.unshift("[]"):r.unshift("unknown"),e=e.object;const s=r.join("");return t||p.includes(s)?s:null}build(){return this.toString().length>0}astGeneric(e,t){if(null===e)throw this.astErrorOutput("NULL ast",e);if(Array.isArray(e)){for(let r=0;r0?s[s.length-1]:0;return new Error(`${e} on line ${s.length}, position ${i.length}:\n ${r}`)}astDebuggerStatement(e,t){return t}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);return t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t}astFunction(e,t){throw new Error(`"astFunction" not defined on ${this.constructor.name}`)}astFunctionDeclaration(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}astFunctionExpression(e,t){return this.isChildFunction(e)?t:this.astFunction(e,t)}isChildFunction(e){for(let t=0;t1?t.push("(",s.join(","),")"):t.push(s[0]),t}astUnaryExpression(e,t){if(this.checkAndUpconvertBitwiseUnary(e,t))return t;if(e.prefix){const r="-"===e.operator||"+"===e.operator;r&&t.push("("),t.push(e.operator),this.astGeneric(e.argument,t),r&&t.push(")")}else this.astGeneric(e.argument,t),t.push(e.operator);return t}checkAndUpconvertBitwiseUnary(e,t){}astUpdateExpression(e,t){return e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t}astLogicalExpression(e,t){return t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),t.push(")"),t}astMemberExpression(e,t){return t}astCallExpression(e,t){return t}astArrayExpression(e,t){return t}getMemberExpressionDetails(e){if("MemberExpression"!==e.type)throw this.astErrorOutput(`Expression ${e.type} not a MemberExpression`,e);let t=null,r=null;const s=this.getVariableSignature(e);switch(s){case"value":return null;case"value.thread.value":case"this.thread.value":case"this.output.value":return{signature:s,type:"Integer",name:e.property.name};case"value[]":if("string"!=typeof e.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.name,{name:t,origin:"user",signature:s,type:this.getVariableType(e.object),xProperty:e.property};case"value[][]":if("string"!=typeof e.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.name,{name:t,origin:"user",signature:s,type:this.getVariableType(e.object.object),yProperty:e.object.property,xProperty:e.property};case"value[][][]":if("string"!=typeof e.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.name,{name:t,origin:"user",signature:s,type:this.getVariableType(e.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value[][][][]":if("string"!=typeof e.object.object.object.object.name)throw this.astErrorOutput("Unexpected expression",e);return t=e.object.object.object.object.name,{name:t,origin:"user",signature:s,type:this.getVariableType(e.object.object.object.object),zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"value.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(this.isAstMathVariable(e))return t=e.property.name,{name:t,origin:"Math",type:"Number",signature:s};switch(e.property.name){case"r":case"g":case"b":case"a":return t=e.object.name,{name:t,property:e.property.name,origin:"user",signature:s,type:"Number"};default:throw this.astErrorOutput("Unexpected expression",e)}case"this.constants.value":if("string"!=typeof e.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:s};case"this.constants.value[]":if("string"!=typeof e.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:s,xProperty:e.property};case"this.constants.value[][]":if("string"!=typeof e.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:s,yProperty:e.object.property,xProperty:e.property};case"this.constants.value[][][]":if("string"!=typeof e.object.object.object.property.name)throw this.astErrorOutput("Unexpected expression",e);if(t=e.object.object.object.property.name,r=this.getConstantType(t),!r)throw this.astErrorOutput("Constant has no type",e);return{name:t,type:r,origin:"constants",signature:s,zProperty:e.object.object.property,yProperty:e.object.property,xProperty:e.property};case"fn()[]":case"fn()[][]":case"[][]":return{signature:s,property:e.property};default:throw this.astErrorOutput("Unexpected expression",e)}}findIdentifierOrigin(e){const t=[this.ast];for(;t.length>0;){const r=t[0];if("VariableDeclarator"===r.type&&r.id&&r.id.name&&r.id.name===e.name)return r;if(t.shift(),r.argument)t.push(r.argument);else if(r.body)t.push(r.body);else if(r.declarations)t.push(r.declarations);else if(Array.isArray(r))for(let e=0;e0;){const e=t.pop();if("ReturnStatement"===e.type)return e;if("FunctionDeclaration"!==e.type)if(e.argument)t.push(e.argument);else if(e.body)t.push(e.body);else if(e.declarations)t.push(e.declarations);else if(Array.isArray(e))for(let r=0;r{const{FunctionNode:r}=h(),{threadLocalName:s}=o();t.exports={CPUFunctionNode:class extends r{get readsCanFault(){return!0}markupUserName(e){return this.isRootKernel&&this.getAssignedArguments().has(e)?`cellShadow_user_${e}`:`user_${e}`}astFunction(e,t){if(!this.isRootKernel){t.push("function"),t.push(" "),t.push(this.name),t.push("(");for(let e=0;e0&&t.push(", "),t.push("user_"),t.push(r)}t.push(") {\n")}if(this.isRootKernel){for(const e of this.getAssignedArguments())t.push(`let cellShadow_user_${e} = user_${e};\n`);t.push("kernelBody: {\n")}for(let r=0;r0&&t.push(r.join(""),";\n"),t.push(`for (let ${e}=0;${e}0&&t.push(`if (!${s.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);return t.push("for (let i = 0; i < LOOP_MAX; i++) {"),t.push("if ("),this.astGeneric(e.test,t),t.push(") {\n"),this.astGeneric(e.body,t),t.push("} else {\n"),t.push("break;\n"),t.push("}\n"),t.push("}\n"),t}astDoWhileStatement(e,t){if("DoWhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=`safeI${this.astKey(e,"_")}`;return t.push(`let ${r} = 0;\n`),t.push("do {"),this.astGeneric(e.body,t),t.push("} while (("),this.astGeneric(e.test,t),t.push(`) && ++${r} < LOOP_MAX);\n`),t}astAssignmentExpression(e,t){const r=this.isState("assignment-as-statement");return r?this.popState("assignment-as-statement"):t.push("("),this.astGeneric(e.left,t),t.push(e.operator),this.astGeneric(e.right,t),r||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let r=0;r0&&t.push(",");const s=r[e],n=this.getDeclaration(s.id);n.valueType||(n.valueType=this.getType(s.init)),this.astGeneric(s,t)}return this.isState("in-for-loop-init")||t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchStatement(e,t){const{discriminant:r,cases:s}=e;t.push("switch ("),this.astGeneric(r,t),t.push(") {\n");for(let e=0;e0&&(this.astGeneric(s[e].consequent,t),t.push("break;\n"))):(t.push("default:\n"),this.astGeneric(s[e].consequent,t),s[e].consequent&&s[e].consequent.length>0&&t.push("break;\n"));t.push("\n}")}astThisExpression(e,t){return t.push("_this"),t}astMemberExpression(e,t){const{signature:r,type:n,property:i,xProperty:a,yProperty:o,zProperty:u,name:l,origin:h}=this.getMemberExpressionDetails(e);switch(r){case"this.thread.value":{const e=s(this,l);return t.push(null===e?`_this.thread.${l}`:e),t}case"this.output.value":switch(l){case"x":t.push("outputX");break;case"y":t.push("outputY");break;case"z":t.push("outputZ");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":default:throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value.value":if("Math"===h)return t.push(Math[l]),t;switch(i){case"r":return t.push(`user_${l}[0]`),t;case"g":return t.push(`user_${l}[1]`),t;case"b":return t.push(`user_${l}[2]`),t;case"a":return t.push(`user_${l}[3]`),t}break;case"this.constants.value":case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":break;case"fn()[]":return this.astGeneric(e.object,t),t.push("["),this.astGeneric(e.property,t),t.push("]"),t;case"fn()[][]":return this.astGeneric(e.object.object,t),t.push("["),this.astGeneric(e.object.property,t),t.push("]"),t.push("["),this.astGeneric(e.property,t),t.push("]"),t}if(!e.computed)switch(n){case"Number":case"Integer":case"Float":case"Boolean":return t.push("user"===h?this.markupUserName(l):`${h}_${l}`),t}const c="user"===h?this.markupUserName(l):`${h}_${l}`;{let e,r;if("constants"===h){const t=this.constants[l];r="Input"===this.constantTypes[l],e=r?t.size:null}else r=this.isInput(l),e=r?this.argumentSizes[this.argumentNames.indexOf(l)]:null;t.push(`${c}`),u&&o?r?(t.push("[("),this.astGeneric(u,t),t.push(`*${this.dynamicArguments?"(outputY * outputX)":e[1]*e[0]})+(`),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(a,t),t.push("]")):(t.push("["),this.astGeneric(u,t),t.push("]"),t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]")):o?r?(t.push("[("),this.astGeneric(o,t),t.push(`*${this.dynamicArguments?"outputX":e[0]})+`),this.astGeneric(a,t),t.push("]")):(t.push("["),this.astGeneric(o,t),t.push("]"),t.push("["),this.astGeneric(a,t),t.push("]")):void 0!==a&&(t.push("["),this.astGeneric(a,t),t.push("]"))}return t}astCallExpression(e,t){if("CallExpression"!==e.type)throw this.astErrorOutput("Unknown CallExpression",e);let r=this.astMemberExpressionUnroll(e.callee);this.calledFunctions.indexOf(r)<0&&this.calledFunctions.push(r),this.isAstMathFunction(e),this.onFunctionCall&&this.onFunctionCall(this.name,r,e.arguments),t.push(r),t.push("(");const s=this.lookupFunctionArgumentTypes(r)||[];for(let n=0;n0&&t.push(", "),this.astGeneric(i,t)}return t.push(")"),t}astArrayExpression(e,t){const r=this.getType(e),s=e.elements.length,n=[];for(let t=0;t{const{utils:r}=i();t.exports={cpuKernelString:function(e,t){const s=[],n=[],i=[],a=!/^function/.test(e.color.toString());if(s.push(" const { context, canvas, constants: incomingConstants } = settings;",` const output = new Int32Array(${JSON.stringify(Array.from(e.output))});`,` const _constantTypes = ${JSON.stringify(e.constantTypes)};`,` const _constants = ${function(e,t){const r=[];for(const s in t){if(!t.hasOwnProperty(s))continue;const n=t[s],i=e[s];switch(n){case"Number":case"Integer":case"Float":case"Boolean":r.push(`${s}:${i}`);break;case"Array(2)":case"Array(3)":case"Array(4)":case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":r.push(`${s}:new ${i.constructor.name}(${JSON.stringify(Array.from(i))})`)}}return`{ ${r.join()} }`}(e.constants,e.constantTypes)};`),n.push(" constants: _constants,"," context,"," output,"," thread: {x: 0, y: 0, z: 0},"),e.graphical){s.push(` const _imageData = context.createImageData(${e.output[0]}, ${e.output[1]});`),s.push(` const _colorData = new Uint8ClampedArray(${e.output[0]} * ${e.output[1]} * 4);`);const t=r.flattenFunctionToString((a?"function ":"")+e.color.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:(e,t)=>null}),o=r.flattenFunctionToString((a?"function ":"")+e.getPixels.toString(),{thisLookup:t=>{switch(t){case"_colorData":return"_colorData";case"_imageData":return"_imageData";case"output":return"output";case"thread":return"this.thread"}return JSON.stringify(e[t])},findDependency:()=>null});n.push(" _imageData,"," _colorData,",` color: ${t},`),i.push(` kernel.getPixels = ${o};`)}const o=[],u=Object.keys(e.constantTypes);for(let t=0;t"this"===t?(a?"function ":"")+e[r].toString():null,thisLookup:e=>{switch(e){case"canvas":return;case"context":return"context"}}});i.push(t),n.push(" _mediaTo2DArray,"),n.push(" _imageTo3DArray,")}else if(-1!==e.argumentTypes.indexOf("HTMLImage")||-1!==o.indexOf("HTMLImage")){const t=r.flattenFunctionToString((a?"function ":"")+e._mediaTo2DArray.toString(),{findDependency:(e,t)=>null,thisLookup:e=>{switch(e){case"canvas":return"settings.canvas";case"context":return"settings.context"}throw new Error("unhandled thisLookup")}});i.push(t),n.push(" _mediaTo2DArray,")}return`function(settings) {\n${s.join("\n")}\n for (const p in _constantTypes) {\n if (!_constantTypes.hasOwnProperty(p)) continue;\n const type = _constantTypes[p];\n switch (type) {\n case 'Number':\n case 'Integer':\n case 'Float':\n case 'Boolean':\n case 'Array(2)':\n case 'Array(3)':\n case 'Array(4)':\n case 'Matrix(2)':\n case 'Matrix(3)':\n case 'Matrix(4)':\n if (incomingConstants.hasOwnProperty(p)) {\n console.warn('constant ' + p + ' of type ' + type + ' cannot be resigned');\n }\n continue;\n }\n if (!incomingConstants.hasOwnProperty(p)) {\n throw new Error('constant ' + p + ' not found');\n }\n _constants[p] = incomingConstants[p];\n }\n const kernel = (function() {\n${e._kernelString}\n })\n .apply({ ${n.join("\n")} });\n ${i.join("\n")}\n return kernel;\n}`}}}),d=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:s}=u(),{CPUFunctionNode:n}=c(),{utils:o}=i(),{cpuKernelString:l}=p();t.exports={CPUKernel:class extends r{static getFeatures(){return this.features}static get features(){return Object.freeze({kernelMap:!0,isIntegerDivisionAccurate:!0})}static get isSupported(){return!0}static isContextMatch(e){return!1}static get mode(){return"cpu"}static nativeFunctionArguments(){return null}static nativeFunctionReturnType(){throw new Error(`Looking up native function return type not supported on ${this.name}`)}static combineKernels(e){return e}static getSignature(e,t){return"cpu"+(t.length>0?":"+t.join(","):"")}constructor(e,t){super(e,t),this._inliningDisabled=!0,this.mergeSettings(e.settings||t),this._imageData=null,this._colorData=null,this._kernelString=null,this._prependedString=[],this.thread={x:0,y:0,z:0},this.translatedSources=null}initCanvas(){return"undefined"!=typeof document?document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(0,0):void 0}initContext(){return this.canvas?this.canvas.getContext("2d",{willReadFrequently:!0}):null}initPlugins(e){return[]}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=o.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=o.getDimensions(t);else{if("NumberTexture"!==t&&"ArrayTexture(4)"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=e[0].output}}if(this.graphical&&2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");this.checkOutput()}translateSource(){if(this.leadingReturnStatement=this.output.length>1?"resultX[x] = ":"result[x] = ",this.subKernels){const e=[];for(let t=0;t1?`resultX_${r}[x] = subKernelResult_${r};\n`:`result_${r}[x] = subKernelResult_${r};\n`)}this.followingReturnStatement=e.join("")}const e=s.fromKernel(this,n);this.translatedSources=e.getPrototypes("kernel"),this.graphical||this.returnType||(this.returnType=e.getKernelResultType())}build(){if(this.built)return;if(null!==this.randomSeed&&console.warn("randomSeed is not supported in cpu mode; Math.random() will be unseeded"),this.setupConstants(),this.setupArguments(arguments),this.validateSettings(arguments),this.buildWithOptimizer(()=>this.translateSource()),this.graphical){const{canvas:e,output:t}=this;if(!e)throw new Error("no canvas available for using graphical output");const r=t[0],s=t[1]||1;e.width=r,e.height=s,this._imageData=this.context.createImageData(r,s),this._colorData=new Uint8ClampedArray(r*s*4)}const e=this.getKernelString();this.kernelString=e,this.debug&&(console.log("Function output:"),console.log(e));try{this.run=new Function([],e).bind(this)()}catch(e){console.error("An error occurred compiling the javascript: ",e)}this.buildSignature(arguments),this.built=!0}color(e,t,r,s){void 0===s&&(s=1),e=Math.floor(255*e),t=Math.floor(255*t),r=Math.floor(255*r),s=Math.floor(255*s);const n=this.output[0],i=this.output[1],a=this.thread.x+(i-this.thread.y-1)*n;this._colorData[4*a+0]=e,this._colorData[4*a+1]=t,this._colorData[4*a+2]=r,this._colorData[4*a+3]=s}getKernelString(){if(null!==this._kernelString)return this._kernelString;let e=null,{translatedSources:t}=this;return t.length>1?t=t.filter(t=>/^function/.test(t)?t:(e=t,!1)):e=t.shift(),this._kernelString=` const LOOP_MAX = ${this._getLoopMaxString()};\n ${this.injectedNative||""}\n const _this = this;\n ${this._resultKernelHeader()}\n ${this._processConstants()}\n return (${this.argumentNames.map(e=>"user_"+e).join(", ")}) => {\n ${this._prependedString.join("")}\n ${this._earlyThrows()}\n ${this._processArguments()}\n ${this.graphical?this._graphicalKernelBody(e):this._resultKernelBody(e)}\n ${t.length>0?t.join("\n"):""}\n };`}toString(){return l(this)}_getLoopMaxString(){return this.loopMaxIterations?` ${parseInt(this.loopMaxIterations)};`:" 1000;"}_processConstants(){if(!this.constants)return"";const e=[];for(let t in this.constants)switch(this.constantTypes[t]){case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":e.push(` const constants_${t} = this._mediaTo2DArray(this.constants.${t});\n`);break;case"HTMLImageArray":e.push(` const constants_${t} = this._imageTo3DArray(this.constants.${t});\n`);break;case"Input":e.push(` const constants_${t} = this.constants.${t}.value;\n`);break;default:e.push(` const constants_${t} = this.constants.${t};\n`)}return e.join("")}_earlyThrows(){if(this.graphical)return"";if(this.immutable)return"";if(!this.pipeline)return"";const e=[];for(let t=0;t`user_${s} === result_${e.name}`).join(" || ");t.push(`user_${s} === result${n?` || ${n}`:""}`)}return`if (${t.join(" || ")}) throw new Error('Source and destination arrays are the same. Use immutable = true');`}_processArguments(){const e=[];for(let t=0;t0?e.width:e.videoWidth,s=e.height>0?e.height:e.videoHeight;t.width=0;e--){const t=a[e]=new Array(r);for(let e=0;e`const result_${e.name} = new ${t}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_mutableKernel1DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const result = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const result_${t.name} = new ${e}(outputX);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}`}_resultMutableKernel1DLoop(e){return` const outputX = _this.output[0];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n this.thread.y = 0;\n this.thread.z = 0;\n ${e}\n }`}_resultImmutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_mutableKernel2DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const result = new Array(outputY);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputY);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = result[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = result_${t.name}[y] = new ${e}(outputX);\n`).join("")}\n }`}_resultMutableKernel2DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n const resultX = result[y];\n ${this._mapSubKernels(e=>`const resultX_${e.name} = result_${e.name}[y] = new ${t}(outputX);\n`).join("")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_graphicalKernel2DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n for (let y = 0; y < outputY; y++) {\n this.thread.z = 0;\n this.thread.y = y;\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }`}_resultImmutableKernel3DLoop(e){const t=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y] = new ${t}(outputX);\n ${this._mapSubKernels(e=>`const resultX_${e.name} = resultY_${e.name}[y] = new ${t}(outputX);\n`).join(" ")}\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_mutableKernel3DResults(){const e=this._getKernelResultTypeConstructorString();return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n const result = new Array(outputZ);\n ${this._mapSubKernels(e=>`const result_${e.name} = new Array(outputZ);\n`).join(" ")}\n ${this._mapSubKernels(e=>`let subKernelResult_${e.name};\n`).join(" ")}\n for (let z = 0; z < outputZ; z++) {\n const resultY = result[z] = new Array(outputY);\n ${this._mapSubKernels(e=>`const resultY_${e.name} = result_${e.name}[z] = new Array(outputY);\n`).join(" ")}\n for (let y = 0; y < outputY; y++) {\n const resultX = resultY[y] = new ${e}(outputX);\n ${this._mapSubKernels(t=>`const resultX_${t.name} = resultY_${t.name}[y] = new ${e}(outputX);\n`).join(" ")}\n }\n }`}_resultMutableKernel3DLoop(e){return` const outputX = _this.output[0];\n const outputY = _this.output[1];\n const outputZ = _this.output[2];\n for (let z = 0; z < outputZ; z++) {\n this.thread.z = z;\n const resultY = result[z];\n for (let y = 0; y < outputY; y++) {\n this.thread.y = y;\n const resultX = resultY[y];\n for (let x = 0; x < outputX; x++) {\n this.thread.x = x;\n ${e}\n }\n }\n }`}_kernelOutput(){return this.subKernels?`\n return {\n result: result,\n ${this.subKernels.map(e=>`${e.property}: result_${e.name}`).join(",\n ")}\n };`:"\n return result;"}_mapSubKernels(e){return null===this.subKernels?[""]:this.subKernels.map(e)}destroy(e){e&&delete this.canvas}static destroyContext(e){}toJSON(){const e=super.toJSON();return e.functionNodes=s.fromKernel(this,n).toJSON(),e}setOutput(e){super.setOutput(e);const[t,r]=this.output;this.graphical&&(this._imageData=this.context.createImageData(t,r),this._colorData=new Uint8ClampedArray(t*r*4))}prependString(e){if(this._kernelString)throw new Error("Kernel already built");this._prependedString.push(e)}hasPrependString(e){return this._prependedString.indexOf(e)>-1}}}}),f=e((e,t)=>{t.exports={}}),m=e((e,t)=>{const{Texture:r}=n();function s(e,t){e.activeTexture(e.TEXTURE15),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST)}t.exports={GLTexture:class extends r{get textureType(){throw new Error(`"textureType" not implemented on ${this.name}`)}clone(){return new this.constructor(this)}beforeMutate(){return this.texture._refs>1&&(this.newTexture(),!0)}cloneTexture(){this.texture._refs--;const{context:e,size:t,texture:r,kernel:n}=this;n.debug&&console.warn("cloning internal texture"),e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),s(e,r),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,r,0);const i=e.createTexture();s(e,i),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),e.copyTexSubImage2D(e.TEXTURE_2D,0,0,0,0,0,t[0],t[1]),i._refs=1,this.texture=i}newTexture(){this.texture._refs--;const e=this.context,t=this.size;this.kernel.debug&&console.warn("new internal texture");const r=e.createTexture();s(e,r),e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,t[0],t[1],0,this.textureFormat,this.textureType,null),r._refs=1,this.texture=r}clear(){if(this.texture._refs){this.texture._refs--;const e=this.context,t=this.texture=e.createTexture();s(e,t);const r=this.size;t._refs=1,e.texImage2D(e.TEXTURE_2D,0,this.internalFormat,r[0],r[1],0,this.textureFormat,this.textureType,null)}const{context:e,texture:t}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.bindTexture(e.TEXTURE_2D,t),s(e,t),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT)}delete(){this._deleted||(this._deleted=!0,this.texture._refs&&(this.texture._refs--,this.texture._refs)||(this.kernel&&this.kernel.deleteTexture?this.kernel.deleteTexture(this.texture):this.context.deleteTexture(this.texture)))}framebuffer(){return this._framebuffer||(this._framebuffer=this.kernel.getRawValueFramebuffer(this.size[0],this.size[1])),this._framebuffer}}}}),g=e((e,t)=>{const{utils:r}=i(),{GLTexture:s}=m();t.exports={GLTextureFloat:class extends s{get textureType(){return this.context.FLOAT}constructor(e){super(e),this.type="ArrayTexture(1)"}renderRawOutput(){const e=this.context,t=this.size;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const r=new Float32Array(t[0]*t[1]*4);return e.readPixels(0,0,t[0],t[1],e.RGBA,e.FLOAT,r),r}renderValues(){return this._deleted?null:this.renderRawOutput()}toArray(){return r.erectFloat(this.renderValues(),this.output[0])}}}}),y=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray2Float:class extends s{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erectArray2(this.renderValues(),this.output[0],this.output[1])}}}}),x=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray2Float2D:class extends s{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erect2DArray2(this.renderValues(),this.output[0],this.output[1])}}}}),b=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray2Float3D:class extends s{constructor(e){super(e),this.type="ArrayTexture(2)"}toArray(){return r.erect3DArray2(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),v=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray3Float:class extends s{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erectArray3(this.renderValues(),this.output[0])}}}}),S=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray3Float2D:class extends s{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erect2DArray3(this.renderValues(),this.output[0],this.output[1])}}}}),T=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray3Float3D:class extends s{constructor(e){super(e),this.type="ArrayTexture(3)"}toArray(){return r.erect3DArray3(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),A=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray4Float:class extends s{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erectArray4(this.renderValues(),this.output[0])}}}}),w=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray4Float2D:class extends s{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erect2DArray4(this.renderValues(),this.output[0],this.output[1])}}}}),_=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureArray4Float3D:class extends s{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return r.erect3DArray4(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),E=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureFloat2D:class extends s{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return r.erect2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),I=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureFloat3D:class extends s{constructor(e){super(e),this.type="ArrayTexture(1)"}toArray(){return r.erect3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),k=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureMemoryOptimized:class extends s{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimizedFloat(this.renderValues(),this.output[0])}}}}),C=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureMemoryOptimized2D:class extends s{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimized2DFloat(this.renderValues(),this.output[0],this.output[1])}}}}),L=e((e,t)=>{const{utils:r}=i(),{GLTextureFloat:s}=g();t.exports={GLTextureMemoryOptimized3D:class extends s{constructor(e){super(e),this.type="MemoryOptimizedNumberTexture"}toArray(){return r.erectMemoryOptimized3DFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),D=e((e,t)=>{const{utils:r}=i(),{GLTexture:s}=m();t.exports={GLTextureUnsigned:class extends s{get textureType(){return this.context.UNSIGNED_BYTE}constructor(e){super(e),this.type="NumberTexture"}renderRawOutput(){const{context:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer()),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture,0);const t=new Uint8Array(this.size[0]*this.size[1]*4);return e.readPixels(0,0,this.size[0],this.size[1],e.RGBA,e.UNSIGNED_BYTE,t),t}renderValues(){return this._deleted?null:new Float32Array(this.renderRawOutput().buffer)}toArray(){return r.erectPackedFloat(this.renderValues(),this.output[0])}}}}),F=e((e,t)=>{const{utils:r}=i(),{GLTextureUnsigned:s}=D();t.exports={GLTextureUnsigned2D:class extends s{constructor(e){super(e),this.type="NumberTexture"}toArray(){return r.erect2DPackedFloat(this.renderValues(),this.output[0],this.output[1])}}}}),$=e((e,t)=>{const{utils:r}=i(),{GLTextureUnsigned:s}=D();t.exports={GLTextureUnsigned3D:class extends s{constructor(e){super(e),this.type="NumberTexture"}toArray(){return r.erect3DPackedFloat(this.renderValues(),this.output[0],this.output[1],this.output[2])}}}}),R=e((e,t)=>{const{GLTextureUnsigned:r}=D();t.exports={GLTextureGraphical:class extends r{constructor(e){super(e),this.type="ArrayTexture(4)"}toArray(){return this.renderValues()}}}}),N=e((e,t)=>{const{Kernel:r}=a(),{utils:s}=i(),{GLTextureArray2Float:n}=y(),{GLTextureArray2Float2D:o}=x(),{GLTextureArray2Float3D:u}=b(),{GLTextureArray3Float:l}=v(),{GLTextureArray3Float2D:h}=S(),{GLTextureArray3Float3D:c}=T(),{GLTextureArray4Float:p}=A(),{GLTextureArray4Float2D:d}=w(),{GLTextureArray4Float3D:f}=_(),{GLTextureFloat:m}=g(),{GLTextureFloat2D:N}=E(),{GLTextureFloat3D:M}=I(),{GLTextureMemoryOptimized:O}=k(),{GLTextureMemoryOptimized2D:G}=C(),{GLTextureMemoryOptimized3D:V}=L(),{GLTextureUnsigned:P}=D(),{GLTextureUnsigned2D:B}=F(),{GLTextureUnsigned3D:z}=$(),{GLTextureGraphical:U}=R();const K={int:"Integer",float:"Number",vec2:"Array(2)",vec3:"Array(3)",vec4:"Array(4)"};t.exports={GLKernel:class extends r{static get mode(){return"gpu"}static getIsFloatRead(){const e=new this("function kernelFunction() {\n return 1;\n }",{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[1],precision:"single",returnType:"Number",tactic:"speed"});e.build(),e.run();const t=e.renderOutput();return e.destroy(!0),1===t[0]}static getIsIntegerDivisionAccurate(){const e=new this(function(e,t){return e[this.thread.x]/t[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[2],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[6,6030401],[3,3991]];e.build.apply(e,t),e.run.apply(e,t);const r=e.renderOutput();return e.destroy(!0),2===r[0]&&1511===r[1]}static getIsSpeedTacticSupported(){const e=new this(function(e){return e[this.thread.x]}.toString(),{context:this.testContext,canvas:this.testCanvas,validate:!1,output:[4],returnType:"Number",precision:"unsigned",tactic:"speed"}),t=[[0,1,2,3]];e.build.apply(e,t),e.run.apply(e,t);const r=e.renderOutput();return e.destroy(!0),0===Math.round(r[0])&&1===Math.round(r[1])&&2===Math.round(r[2])&&3===Math.round(r[3])}static get testCanvas(){throw new Error(`"testCanvas" not defined on ${this.name}`)}static get testContext(){throw new Error(`"testContext" not defined on ${this.name}`)}static getFeatures(){const e=this.testContext,t=this.getIsDrawBuffers();return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),isTextureFloat:this.getIsTextureFloat(),isDrawBuffers:t,kernelMap:t,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static setupFeatureChecks(){throw new Error(`"setupFeatureChecks" not defined on ${this.name}`)}static getSignature(e,t){return e.getVariablePrecisionString()+(t.length>0?":"+t.join(","):"")}setFixIntegerDivisionAccuracy(e){return this.fixIntegerDivisionAccuracy=e,this}setPrecision(e){return this.precision=e,this}setFloatTextures(e){return s.warnDeprecated("method","setFloatTextures","setOptimizeFloatMemory"),this.floatTextures=e,this}static nativeFunctionArguments(e){const t=[],r=[],s=[],n=/^[a-zA-Z_]/,i=/[a-zA-Z_0-9]/;let a=0,o=null,u=null;for(;a0?s[s.length-1]:null;if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"*"!==h)if("MULTI_LINE_COMMENT"!==c||"*"!==l||"/"!==h)if("FUNCTION_ARGUMENTS"!==c||"/"!==l||"/"!==h)if("COMMENT"!==c||"\n"!==l)if(null!==c||"("!==l){if("FUNCTION_ARGUMENTS"===c){if(")"===l){s.pop();break}if("f"===l&&"l"===h&&"o"===e[a+2]&&"a"===e[a+3]&&"t"===e[a+4]&&" "===e[a+5]){s.push("DECLARE_VARIABLE"),u="float",o="",a+=6;continue}if("i"===l&&"n"===h&&"t"===e[a+2]&&" "===e[a+3]){s.push("DECLARE_VARIABLE"),u="int",o="",a+=4;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"2"===e[a+3]&&" "===e[a+4]){s.push("DECLARE_VARIABLE"),u="vec2",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"3"===e[a+3]&&" "===e[a+4]){s.push("DECLARE_VARIABLE"),u="vec3",o="",a+=5;continue}if("v"===l&&"e"===h&&"c"===e[a+2]&&"4"===e[a+3]&&" "===e[a+4]){s.push("DECLARE_VARIABLE"),u="vec4",o="",a+=5;continue}}else if("DECLARE_VARIABLE"===c){if(""===o){if(" "===l){a++;continue}if(!n.test(l))throw new Error("variable name is not expected string")}o+=l,i.test(h)||(s.pop(),r.push(o),t.push(K[u]))}a++}else s.push("FUNCTION_ARGUMENTS"),a++;else s.pop(),a++;else s.push("COMMENT"),a+=2;else s.pop(),a+=2;else s.push("MULTI_LINE_COMMENT"),a+=2}if(s.length>0)throw new Error("GLSL function was not parsable");return{argumentNames:r,argumentTypes:t}}static nativeFunctionReturnType(e){return K[e.match(/int|float|vec[2-4]/)[0]]}static combineKernels(e,t){e.apply(null,arguments);const{texSize:r,context:n,threadDim:i}=t.texSize;let a;if("single"===t.precision){const e=r[0],t=Math.ceil(r[1]/4);a=new Float32Array(e*t*4*4),n.readPixels(0,0,e,4*t,n.RGBA,n.FLOAT,a)}else{const e=new Uint8Array(r[0]*r[1]*4);n.readPixels(0,0,r[0],r[1],n.RGBA,n.UNSIGNED_BYTE,e),a=new Float32Array(e.buffer)}return a=a.subarray(0,i[0]*i[1]*i[2]),1===t.output.length?a:2===t.output.length?s.splitArray(a,t.output[0]):3===t.output.length?s.splitArray(a,t.output[0]*t.output[1]).map(function(e){return s.splitArray(e,t.output[0])}):void 0}constructor(e,t){super(e,t),this.transferValues=null,this.formatValues=null,this.TextureConstructor=null,this.renderOutput=null,this.renderRawOutput=null,this.texSize=null,this.translatedSource=null,this.compiledFragmentShader=null,this.compiledVertexShader=null,this.switchingKernels=null,this._textureSwitched=null,this._mappedTextureSwitched=null}checkTextureSize(){const{features:e}=this.constructor;if(this.texSize[0]>e.maxTextureSize||this.texSize[1]>e.maxTextureSize)throw new Error(`Texture size [${this.texSize[0]},${this.texSize[1]}] generated by kernel is larger than supported size [${e.maxTextureSize},${e.maxTextureSize}]`)}translateSource(){throw new Error(`"translateSource" not defined on ${this.constructor.name}`)}pickRenderStrategy(e){if(this.graphical)return this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=e=>e,this.TextureConstructor=U,null;if("unsigned"===this.precision)if(this.renderRawOutput=this.readPackedPixelsToUint8Array,this.transferValues=this.readPackedPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=z,null):this.output[1]>0?(this.TextureConstructor=B,null):(this.TextureConstructor=P,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else switch(null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.renderOutput=this.renderValues,this.output[2]>0?(this.TextureConstructor=z,this.formatValues=s.erect3DPackedFloat,null):this.output[1]>0?(this.TextureConstructor=B,this.formatValues=s.erect2DPackedFloat,null):(this.TextureConstructor=P,this.formatValues=s.erectPackedFloat,null);case"Array(2)":case"Array(3)":case"Array(4)":return this.requestFallback(e,`${this.returnType} output requires single precision, which this context does not support`)}else{if("single"!==this.precision)throw new Error(`unhandled precision of "${this.precision}"`);if(this.renderRawOutput=this.readFloatPixelsToFloat32Array,this.transferValues=this.readFloatPixelsToFloat32Array,this.pipeline)switch(this.renderOutput=this.renderTexture,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToTextures),this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.optimizeFloatMemory?this.output[2]>0?(this.TextureConstructor=V,null):this.output[1]>0?(this.TextureConstructor=G,null):(this.TextureConstructor=O,null):this.output[2]>0?(this.TextureConstructor=M,null):this.output[1]>0?(this.TextureConstructor=N,null):(this.TextureConstructor=m,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,null):this.output[1]>0?(this.TextureConstructor=o,null):(this.TextureConstructor=n,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,null):this.output[1]>0?(this.TextureConstructor=h,null):(this.TextureConstructor=l,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,null):this.output[1]>0?(this.TextureConstructor=d,null):(this.TextureConstructor=p,null)}if(this.renderOutput=this.renderValues,null!==this.subKernels&&(this.renderKernels=this.renderKernelsToArrays),this.optimizeFloatMemory)switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=V,this.formatValues=s.erectMemoryOptimized3DFloat,null):this.output[1]>0?(this.TextureConstructor=G,this.formatValues=s.erectMemoryOptimized2DFloat,null):(this.TextureConstructor=O,this.formatValues=s.erectMemoryOptimizedFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=s.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=s.erect2DArray2,null):(this.TextureConstructor=n,this.formatValues=s.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=s.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=s.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=s.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=s.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=s.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=s.erectArray4,null)}else switch(this.returnType){case"LiteralInteger":case"Float":case"Number":case"Integer":return this.output[2]>0?(this.TextureConstructor=M,this.formatValues=s.erect3DFloat,null):this.output[1]>0?(this.TextureConstructor=N,this.formatValues=s.erect2DFloat,null):(this.TextureConstructor=m,this.formatValues=s.erectFloat,null);case"Array(2)":return this.output[2]>0?(this.TextureConstructor=u,this.formatValues=s.erect3DArray2,null):this.output[1]>0?(this.TextureConstructor=o,this.formatValues=s.erect2DArray2,null):(this.TextureConstructor=n,this.formatValues=s.erectArray2,null);case"Array(3)":return this.output[2]>0?(this.TextureConstructor=c,this.formatValues=s.erect3DArray3,null):this.output[1]>0?(this.TextureConstructor=h,this.formatValues=s.erect2DArray3,null):(this.TextureConstructor=l,this.formatValues=s.erectArray3,null);case"Array(4)":return this.output[2]>0?(this.TextureConstructor=f,this.formatValues=s.erect3DArray4,null):this.output[1]>0?(this.TextureConstructor=d,this.formatValues=s.erect2DArray4,null):(this.TextureConstructor=p,this.formatValues=s.erectArray4,null)}}throw new Error(`unhandled return type "${this.returnType}"`)}getKernelString(){throw new Error("abstract method call")}getMainResultTexture(){switch(this.returnType){case"LiteralInteger":case"Float":case"Integer":case"Number":return this.getMainResultNumberTexture();case"Array(2)":return this.getMainResultArray2Texture();case"Array(3)":return this.getMainResultArray3Texture();case"Array(4)":return this.getMainResultArray4Texture();default:throw new Error(`unhandled returnType type ${this.returnType}`)}}getMainResultKernelNumberTexture(){throw new Error("abstract method call")}getMainResultSubKernelNumberTexture(){throw new Error("abstract method call")}getMainResultKernelArray2Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray2Texture(){throw new Error("abstract method call")}getMainResultKernelArray3Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray3Texture(){throw new Error("abstract method call")}getMainResultKernelArray4Texture(){throw new Error("abstract method call")}getMainResultSubKernelArray4Texture(){throw new Error("abstract method call")}getMainResultGraphical(){throw new Error("abstract method call")}getMainResultMemoryOptimizedFloats(){throw new Error("abstract method call")}getMainResultPackedPixels(){throw new Error("abstract method call")}getMainResultString(){return this.graphical?this.getMainResultGraphical():"single"===this.precision?this.optimizeFloatMemory?this.getMainResultMemoryOptimizedFloats():this.getMainResultTexture():this.getMainResultPackedPixels()}getMainResultNumberTexture(){return s.linesToString(this.getMainResultKernelNumberTexture())+s.linesToString(this.getMainResultSubKernelNumberTexture())}getMainResultArray2Texture(){return s.linesToString(this.getMainResultKernelArray2Texture())+s.linesToString(this.getMainResultSubKernelArray2Texture())}getMainResultArray3Texture(){return s.linesToString(this.getMainResultKernelArray3Texture())+s.linesToString(this.getMainResultSubKernelArray3Texture())}getMainResultArray4Texture(){return s.linesToString(this.getMainResultKernelArray4Texture())+s.linesToString(this.getMainResultSubKernelArray4Texture())}getFloatTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} float;\n`}getIntTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic,!0)} int;\n`}getSampler2DTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2D;\n`}getSampler2DArrayTacticDeclaration(){return`precision ${this.getVariablePrecisionString(this.texSize,this.tactic)} sampler2DArray;\n`}renderTexture(){return this.immutable?this.texture.clone():this.texture}readPackedPixelsToUint8Array(){if("unsigned"!==this.precision)throw new Error('Requires this.precision to be "unsigned"');const{texSize:e,context:t}=this,r=new Uint8Array(e[0]*e[1]*4);return t.readPixels(0,0,e[0],e[1],t.RGBA,t.UNSIGNED_BYTE,r),r}readPackedPixelsToFloat32Array(){return new Float32Array(this.readPackedPixelsToUint8Array().buffer)}readFloatPixelsToFloat32Array(){if("single"!==this.precision)throw new Error('Requires this.precision to be "single"');const{texSize:e,context:t}=this,r=e[0],s=e[1],n=new Float32Array(r*s*4);return t.readPixels(0,0,r,s,t.RGBA,t.FLOAT,n),n}getPixels(e){const{context:t,output:r}=this,[n,i]=r,a=new Uint8Array(n*i*4);t.readPixels(0,0,n,i,t.RGBA,t.UNSIGNED_BYTE,a);const o=new Uint8ClampedArray((e?a:s.flipPixels(a,n,i)).buffer);return this.asyncMode?Promise.resolve(o):o}renderKernelsToArrays(){const e={result:this.renderOutput()};for(let t=0;t0){for(let e=0;e0){const{mappedTextures:r}=this;for(let s=0;s{const{utils:r}=i(),{FunctionNode:s}=h(),n={"<":"ceil",">=":"ceil",">":"floor","<=":"floor"};function a(e){if(!e||"object"!=typeof e)return!0;if(Array.isArray(e))return e.every(a);if("UpdateExpression"===e.type||"AssignmentExpression"===e.type||"SequenceExpression"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&!a(e[t]))return!1;return!0}function o(e){let t=!1;function r(e){if(!e||"object"!=typeof e||t)return!1;if(Array.isArray(e))return e.some(r);if("MemberExpression"===e.type&&e.computed)return!0;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t]))return!0;return!1}return function e(s){if(s&&"object"==typeof s&&!t)if(Array.isArray(s))s.forEach(e);else if("MemberExpression"===s.type&&s.computed&&r(s.property))t=!0;else for(const t in s)"loc"!==t&&"range"!==t&&"parent"!==t&&e(s[t])}(e),t}function u(e,t){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>u(e,t));if("CallExpression"===e.type&&"Identifier"===e.callee.type&&e.callee.name===t)return!0;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&u(e[r],t))return!0;return!1}function l(e){let t=!1;return function e(r){if(r&&"object"==typeof r&&!t)if(Array.isArray(r))r.forEach(e);else if("CallExpression"===r.type&&"Identifier"===r.callee.type&&r.arguments.some(e=>u(e,r.callee.name)))t=!0;else for(const t in r)"loc"!==t&&"range"!==t&&"parent"!==t&&e(r[t])}(e),t}function c(e){const t="ExpressionStatement"===e.type&&"AssignmentExpression"===e.expression.type?e.expression:null;return function e(r){if(!r||"object"!=typeof r)return!0;if(Array.isArray(r))return r.every(e);if("string"==typeof r.type){if("UpdateExpression"===r.type||"SequenceExpression"===r.type)return!1;if("AssignmentExpression"===r.type&&r!==t)return!1}for(const t in r)if("loc"!==t&&"range"!==t&&"parent"!==t&&!e(r[t]))return!1;return!0}(e)}const p={"Matrix(2)":2,"Matrix(3)":3,"Matrix(4)":4},d={Array:"sampler2D","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4","Matrix(2)":"mat2","Matrix(3)":"mat3","Matrix(4)":"mat4",Array2D:"sampler2D",Array3D:"sampler2D",Boolean:"bool",Float:"float",Input:"sampler2D",Integer:"int",Number:"float",LiteralInteger:"float",NumberTexture:"sampler2D",MemoryOptimizedNumberTexture:"sampler2D","ArrayTexture(1)":"sampler2D","ArrayTexture(2)":"sampler2D","ArrayTexture(3)":"sampler2D","ArrayTexture(4)":"sampler2D",HTMLVideo:"sampler2D",HTMLCanvas:"sampler2D",OffscreenCanvas:"sampler2D",HTMLImage:"sampler2D",ImageBitmap:"sampler2D",ImageData:"sampler2D",HTMLImageArray:"sampler2DArray"},f={"===":"==","!==":"!="};function m(e){return!!e&&("UnaryExpression"!==e.type||"-"!==e.operator&&"+"!==e.operator?"Literal"===e.type&&"number"==typeof e.value&&!Number.isInteger(e.value):m(e.argument))}t.exports={WebGLFunctionNode:class extends s{constructor(e,t){super(e,t),t&&t.hasOwnProperty("fixIntegerDivisionAccuracy")&&(this.fixIntegerDivisionAccuracy=t.fixIntegerDivisionAccuracy)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const r=this.getType(e.consequent),s=this.getType(e.alternate);return null===r&&null===s?(t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t):(t.push("("),this.astGeneric(e.test,t),t.push("?"),this.astGeneric(e.consequent,t),t.push(":"),this.astGeneric(e.alternate,t),t.push(")"),t)}astFunction(e,t){if(this.isRootKernel)t.push("void");else{this.returnType||this.findLastReturn()&&(this.returnType=this.getType(e.body),"LiteralInteger"===this.returnType&&(this.returnType="Number"));const{returnType:r}=this;if(r){const e=d[r];if(!e)throw new Error(`unknown type ${r}`);t.push(e)}else t.push("void")}if(t.push(" "),t.push(this.name),t.push("("),!this.isRootKernel)for(let s=0;s0&&t.push(", ");let i=this.argumentTypes[this.argumentNames.indexOf(n)];if(!i)throw this.astErrorOutput(`Unknown argument ${n} type`,e);"LiteralInteger"===i&&(this.argumentTypes[s]=i="Number");const a=d[i];if(!a)throw this.astErrorOutput("Unexpected expression",e);const o=r.sanitizeName(n);"sampler2D"===a||"sampler2DArray"===a?t.push(`${a} user_${o},ivec2 user_${o}Size,ivec3 user_${o}Dim`):t.push(`${a} user_${o}`)}if(t.push(") {\n"),this.isRootKernel){const e=this.getAssignedArguments();for(let s=0;s>":"bitwiseSignedRightShift",">>>":"bitwiseZeroFillRightShift"}[e.operator];if(!r)return null;switch(t.push(r),t.push("("),this.getType(e.left)){case"Number":case"Float":this.castValueToInteger(e.left,t);break;case"LiteralInteger":this.castLiteralToInteger(e.left,t);break;default:this.astGeneric(e.left,t)}switch(t.push(","),this.getType(e.right)){case"Number":case"Float":this.castValueToInteger(e.right,t);break;case"LiteralInteger":this.castLiteralToInteger(e.right,t);break;default:this.astGeneric(e.right,t)}return t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){const r={"~":"bitwiseNot"}[e.operator];if(!r)return null;switch(t.push(r),t.push("("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("int("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("float("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const s=this.getType(e),n=r.sanitizeName(e.name);if("Infinity"===e.name)t.push("3.402823466e+38");else if("Boolean"===s)if(this.argumentNames.indexOf(n)>-1){const r=this.markupUserName(e.name);t.push(r.startsWith("cellShadow_")?r:`bool(${r})`)}else t.push(`user_${n}`);else t.push(this.markupUserName(e.name));return t}markupUserName(e){const t=r.sanitizeName(e);if(this.isRootKernel&&this.getAssignedArguments().has(e)){const r=this.argumentNames.indexOf(e),s=-1===r?null:d[this.argumentTypes[r]];if("float"===s||"int"===s||"bool"===s)return`cellShadow_user_${t}`}return`user_${t}`}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const r=[],s=[],n=[],i=[];let a=null;if(e.init)if("VariableDeclaration"!==e.init.type)a=!1,this.astGeneric(e.init,r),r.push(";");else{const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,r);for(let e=0;e{const t=this.getDeclaration(e);return null!==t&&r.has(t)},a=e=>{if(e&&"object"==typeof e&&!n)if(Array.isArray(e))for(const t of e)a(t);else if("ForStatement"!==e.type||!e.init||"VariableDeclaration"!==e.init.type||!e.init.declarations.some(e=>e.id&&"Identifier"===e.id.type&&s.has(e.id.name)))if("AssignmentExpression"===e.type&&"Identifier"===e.left.type&&i(e.left))n=!0;else if("UpdateExpression"===e.type&&"Identifier"===e.argument.type&&i(e.argument))n=!0;else for(const t in e){if("loc"===t||"range"===t||"parent"===t)continue;const r=e[t];r&&"object"==typeof r&&a(r)}};return a(e.body),!n&&e.test&&a(e.test),n}emitForParts(e,t){const{initArr:r,testArr:s,updateArr:n,bodyArr:i,isSafe:a}=e;if(a){const e=r.join(""),a=";"!==e[e.length-1];t.push(`for (${e}${a?";":""}${s.join("")};${n.join("")}){\n`),t.push(i.join("")),t.push("}\n")}else{const e=this.getInternalVariableName("safeI");r.length>0&&t.push(r.join(""),"\n"),t.push(`for (int ${e}=0;${e}0&&t.push(`if (!${s.join("")}) break;\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=this.getInternalVariableName("safeI");return t.push(`for (int ${r}=0;${r}0){if (!`),this.astGeneric(e.test,t),t.push(") break;}\n"),this.astGeneric(e.body,t),t.push("}\n"),t}astAssignmentExpression(e,t){const r=this.isState("assignment-as-statement");if(r?this.popState("assignment-as-statement"):t.push("("),"%="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("mod("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else if("**="===e.operator)this.astGeneric(e.left,t),t.push("="),t.push("pow("),this.astGeneric(e.left,t),t.push(","),this.astGeneric(e.right,t),t.push(")");else{const r=this.getType(e.left),s=this.getType(e.right);this.astGeneric(e.left,t),t.push(e.operator),"Integer"!==r&&"Integer"===s?(t.push("float("),this.astGeneric(e.right,t),t.push(")")):"Integer"===r&&"LiteralInteger"===s?this.castLiteralToInteger(e.right,t):this.astGeneric(e.right,t)}return r||t.push(")"),t}astBlockStatement(e,t){if(this.isState("loop-body")){this.pushState("block-body");for(let r=0;rnull!==e&&(o(e)||l(e))))return null;const i=e=>JSON.parse(JSON.stringify(e)),a=e=>({type:"IfStatement",test:{type:"UnaryExpression",operator:"!",prefix:!0,argument:e},consequent:{type:"BlockStatement",body:[{type:"BreakStatement",label:null}]},alternate:null}),u=e=>"VariableDeclaration"===e.type?e:{type:"ExpressionStatement",expression:e},h="BlockStatement"===e.body.type?e.body.body.slice():[e.body],c=(e,t)=>{const r=e=>{if(!e||"object"!=typeof e)return e;if(Array.isArray(e))return e.map(r);switch(e.type){case"ContinueStatement":return{type:"BlockStatement",body:[...t(),e]};case"ForStatement":case"WhileStatement":case"DoWhileStatement":default:return e;case"IfStatement":return{...e,consequent:r(e.consequent),alternate:r(e.alternate)};case"BlockStatement":return{...e,body:e.body.map(r)};case"SwitchStatement":return{...e,cases:e.cases.map(e=>({...e,consequent:e.consequent.map(r)}))}}};return e.map(r)},p=[];"DoWhileStatement"===t?(p.push(...s?c(h,()=>[a(i(s))]):h),s&&p.push(a(s))):(s&&p.push(a(s)),p.push(...n?c(h,()=>[u(i(n))]):h),n&&p.push(u(n)));const d={type:"BlockStatement",body:[...r?[u(r)]:[],{type:"WhileStatement",test:{type:"Literal",value:!0,raw:"true"},body:{type:"BlockStatement",body:p}}]};return this.stampSyntheticNodes(d),d}stampSyntheticNodes(e){let t=this.syntheticNodeId||1073741824;const r=e=>{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(r);else{"string"==typeof e.type&&void 0===e.start&&(e.start=t,e.end=t+1,t+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t])}};r(e),this.syntheticNodeId=t}linearizeStatement(e){const t=[];let r=!1,s=this.linearTempId||0;const n=e=>({type:"Identifier",name:e}),i=(e,t,r)=>({type:"VariableDeclaration",kind:e,declarations:[{type:"VariableDeclarator",id:n(t),init:r}]}),o=(e,t)=>{const r="hoistSeq"+s++;return e.push(i("const",r,t)),n(r)},l=e=>!a(e),h=(e,t)=>{if(r||!e||"object"!=typeof e)return e;switch(e.type){case"Identifier":case"Literal":case"ThisExpression":return e;case"MemberExpression":{const r=h(e.object,t),s=e.computed?h(e.property,t):e.property;return{...e,object:r,property:s}}case"CallExpression":{const r=e.arguments.map(e=>h(e,t));if("Identifier"===e.callee.type)for(let s=0;sh(e,t))};case"UpdateExpression":{if("Identifier"!==e.argument.type)return r=!0,e;if(e.prefix)return t.push({type:"ExpressionStatement",expression:e}),o(t,e.argument);const s=o(t,e.argument);return t.push({type:"ExpressionStatement",expression:e}),s}case"AssignmentExpression":{if("Identifier"!==e.left.type)return r=!0,e;const s=h(e.right,t);return t.push({type:"ExpressionStatement",expression:{...e,right:s}}),o(t,e.left)}case"SequenceExpression":for(let r=0;r({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:n(e),right:t}});return o.push(d(a,c)),u.push(d(a,p)),t.push({type:"IfStatement",test:r,consequent:{type:"BlockStatement",body:o},alternate:{type:"BlockStatement",body:u}}),n(a)}case"LogicalExpression":{if(!l(e.right))return{...e,left:h(e.left,t)};const r=h(e.left,t),a="hoistSeq"+s++;t.push(i("let",a,r));const o=[],u=h(e.right,o);return o.push({type:"ExpressionStatement",expression:{type:"AssignmentExpression",operator:"=",left:n(a),right:u}}),t.push({type:"IfStatement",test:"&&"===e.operator?n(a):{type:"UnaryExpression",operator:"!",prefix:!0,argument:n(a)},consequent:{type:"BlockStatement",body:o},alternate:null}),n(a)}default:return r=!0,e}};switch(e.type){case"ExpressionStatement":{const r=e.expression;if("AssignmentExpression"===r.type&&"Identifier"===r.left.type){const e=h(r.right,t);t.push({type:"ExpressionStatement",expression:{...r,right:e}})}else{const e=h(r,t);"UpdateExpression"!==e.type&&"AssignmentExpression"!==e.type||t.push({type:"ExpressionStatement",expression:e})}break}case"VariableDeclaration":for(let r=0;r{if(e&&"object"==typeof e)if(Array.isArray(e))e.forEach(p);else{"string"==typeof e.type&&void 0===e.start&&(e.start=c,e.end=c+1,c+=2);for(const t in e)"loc"!==t&&"range"!==t&&"parent"!==t&&p(e[t])}};return p(t),this.syntheticNodeId=c,t}astStatementWithHoisting(e,t){switch(e.type){case"ExpressionStatement":case"VariableDeclaration":case"ReturnStatement":{if(!c(e))return this.astGeneric(e,t);const r=this.hoistedIndexReads,s=this.hoistedIndexReads=[],n=[];return this.astGeneric(e,n),this.hoistedIndexReads=r,t.push(...s,...n),t}default:return this.astGeneric(e,t)}}astVariableDeclaration(e,t){const s=e.declarations;if(!s||!s[0]||!s[0].init)throw this.astErrorOutput("Unexpected expression",e);const n=[];let i=null;const a=[];let o=[];for(let t=0;t0&&a.push(o.join(",")),n.push(a.join(";")),t.push(n.join("")),t.push(";"),t}astIfStatement(e,t){return t.push("if ("),this.astGeneric(e.test,t),t.push(")"),"BlockStatement"===e.consequent.type?this.astGeneric(e.consequent,t):(t.push(" {\n"),this.astGeneric(e.consequent,t),t.push("\n}\n")),e.alternate&&(t.push("else "),"BlockStatement"===e.alternate.type||"IfStatement"===e.alternate.type?this.astGeneric(e.alternate,t):(t.push(" {\n"),this.astGeneric(e.alternate,t),t.push("\n}\n"))),t}astSwitchCaseConsequent(e,t){const r=[];for(let t=0;t{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&t(e[r]))return!0;return!1};if(t(r[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",r[e])}for(let e=0;er+1){l=!0,this.astSwitchCaseConsequent(s[r].consequent,u);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(s[r].consequent,t),t.push("\n}")}return l&&(t.push(" else {"),t.push(u.join("")),t.push("}")),t}astThisExpression(e,t){return t.push("this"),t}astMemberExpression(e,t){const{property:s,name:n,signature:i,origin:a,type:o,xProperty:u,yProperty:l,zProperty:h}=this.getMemberExpressionDetails(e);switch(i){case"value.thread.value":case"this.thread.value":if("x"!==n&&"y"!==n&&"z"!==n)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`threadId.${n}`),t;case"this.output.value":if(this.dynamicOutput)switch(n){case"x":this.isState("casting-to-float")?t.push("float(uOutputDim.x)"):t.push("uOutputDim.x");break;case"y":this.isState("casting-to-float")?t.push("float(uOutputDim.y)"):t.push("uOutputDim.y");break;case"z":this.isState("casting-to-float")?t.push("float(uOutputDim.z)"):t.push("uOutputDim.z");break;default:throw this.astErrorOutput("Unexpected expression",e)}else switch(n){case"x":this.isState("casting-to-integer")?t.push(this.output[0]):t.push(this.output[0],".0");break;case"y":this.isState("casting-to-integer")?t.push(this.output[1]):t.push(this.output[1],".0");break;case"z":this.isState("casting-to-integer")?t.push(this.output[2]):t.push(this.output[2],".0");break;default:throw this.astErrorOutput("Unexpected expression",e)}return t;case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===a)return t.push(Math[n]),t;const i=r.sanitizeName(n);switch(s){case"r":return t.push(`user_${i}.r`),t;case"g":return t.push(`user_${i}.g`),t;case"b":return t.push(`user_${i}.b`),t;case"a":return t.push(`user_${i}.a`),t}break;case"this.constants.value":if(void 0===u)switch(o){case"Array(2)":case"Array(3)":case"Array(4)":return t.push(`constants_${r.sanitizeName(n)}`),t}case"this.constants.value[]":case"this.constants.value[][]":case"this.constants.value[][][]":case"this.constants.value[][][][]":break;case"fn()[]":return this.astCallExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(s)),t.push("]"),t;case"fn()[][]":{const r=e.object.property,s=e.property,n=p[this.getType(e.object.object)],i=e=>"LiteralInteger"===this.getType(e);return!n||i(r)&&i(s)?(this.astCallExpression(e.object.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(r)),t.push("]"),t.push("["),t.push(this.memberExpressionPropertyMarkup(s)),t.push("]"),t):(t.push(`getMatrix${n}(`),this.astCallExpression(e.object.object,t),t.push(", "),t.push(this.memberExpressionPropertyMarkup(r)),t.push(", "),t.push(this.memberExpressionPropertyMarkup(s)),t.push(")"),t)}case"[][]":return this.astArrayExpression(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(s)),t.push("]"),t;default:throw this.astErrorOutput("Unexpected expression",e)}if(!1===e.computed)switch(o){case"Number":case"Integer":case"Float":case"Boolean":return t.push(`${a}_${r.sanitizeName(n)}`),t}const c=`${a}_${r.sanitizeName(n)}`;switch(o){case"Array(2)":case"Array(3)":case"Array(4)":this.astGeneric(e.object,t),t.push("["),t.push(this.memberExpressionPropertyMarkup(u)),t.push("]");break;case"HTMLImageArray":t.push(`getImage3D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(1)":t.push(`getFloatFromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(2)":case"Array2D(2)":case"Array3D(2)":t.push(`getMemoryOptimizedVec2(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(2)":t.push(`getVec2FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(3)":case"Array2D(3)":case"Array3D(3)":t.push(`getMemoryOptimizedVec3(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(3)":t.push(`getVec3FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Array1D(4)":case"Array2D(4)":case"Array3D(4)":t.push(`getMemoryOptimizedVec4(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"ArrayTexture(4)":case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLVideo":t.push(`getVec4FromSampler2D(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"NumberTexture":case"Array":case"Array2D":case"Array3D":case"Array4D":case"Input":case"Number":case"Float":case"Integer":if("single"===this.precision)t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");else{const e="user"===a?this.lookupFunctionArgumentBitRatio(this.name,n):this.constantBitRatios[n];switch(e){case 1:t.push(`get8(${c}, ${c}Size, ${c}Dim, `);break;case 2:t.push(`get16(${c}, ${c}Size, ${c}Dim, `);break;case 4:case 0:t.push(`get32(${c}, ${c}Size, ${c}Dim, `);break;default:throw new Error(`unhandled bit ratio of ${e}`)}this.memberExpressionXYZ(u,l,h,t),t.push(")")}break;case"MemoryOptimizedNumberTexture":t.push(`getMemoryOptimized32(${c}, ${c}Size, ${c}Dim, `),this.memberExpressionXYZ(u,l,h,t),t.push(")");break;case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`${c}[${this.memberExpressionPropertyMarkup(l)}]`),l&&t.push(`[${this.memberExpressionPropertyMarkup(u)}]`);break;default:throw new Error(`unhandled member expression "${o}"`)}return t}astCallExpression(e,t){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);let s=null;const n=this.isAstMathFunction(e);if(s=n||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!s)throw this.astErrorOutput("Unhandled function, couldn't find name",e);switch(s){case"pow":s="_pow";break;case"round":s="_round"}if(this.calledFunctions.indexOf(s)<0&&this.calledFunctions.push(s),"random"===s&&this.plugins&&this.plugins.length>0)for(let e=0;e0&&t.push(", "),"Integer"===n)this.castValueToFloat(s,t);else this.astGeneric(s,t)}else{const n=this.lookupFunctionArgumentTypes(s)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(s,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("int("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("float("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.pushState("building-integer"),this.astGeneric(a,t),this.popState("building-integer");continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){if("Identifier"===a.type)t.push(`user_${r.sanitizeName(a.name)}`);else{if("ArrayExpression"!==a.type&&"MemberExpression"!==a.type&&"CallExpression"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.astGeneric(a,t)}continue}break;case"HTMLCanvas":case"OffscreenCanvas":case"HTMLImage":case"ImageBitmap":case"ImageData":case"HTMLImageArray":case"HTMLVideo":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":case"Array":case"Input":if(o===u){if("Identifier"!==a.type)throw this.astErrorOutput(`Unhandled argument type ${a.type}`,e);this.triggerImplyArgumentBitRatio(this.name,a.name,s,i);const n=r.sanitizeName(a.name);t.push(`user_${n},user_${n}Size,user_${n}Dim`);continue}}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),t}astArrayExpression(e,t){const r=this.getType(e),s=e.elements.length;switch(r){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":t.push(`mat${s}(`);break;default:t.push(`vec${s}(`)}for(let r=0;r0&&t.push(", ");const s=e.elements[r];this.astGeneric(s,t)}return t.push(")"),t}memberExpressionXYZ(e,t,r,s){return r?s.push(this.memberExpressionPropertyMarkup(r),", "):s.push("0, "),t?s.push(this.memberExpressionPropertyMarkup(t),", "):s.push("0, "),s.push(this.memberExpressionPropertyMarkup(e)),s}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer");break;default:this.astGeneric(e,t)}const s=t.join("");if(this.hoistedIndexReads&&/\b\w+\((user_|constants_)\w+, \1\w+Size/.test(s)){const e=`hoisted_${this.hoistedIndexReads.length}_${r.sanitizeName(this.name)}`,t=s.startsWith("int(");return this.hoistedIndexReads.push(`${t?"int":"float"} ${e}=${s};\n`),e}return s}}}}),O=e((e,t)=>{t.exports={name:"math-random-uniformly-distributed",onBeforeRun:e=>{if(null===e.randomSeed||void 0===e.randomSeed)return e.setUniform1f("randomSeed1",Math.random()),void e.setUniform1f("randomSeed2",Math.random());e._mathRandomGenerator&&e._mathRandomGeneratorSeed===e.randomSeed||(e._mathRandomGenerator=function(e){let t=e>>>0;return function(){t=t+1831565813>>>0;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(e.randomSeed),e._mathRandomGeneratorSeed=e.randomSeed),e.setUniform1f("randomSeed1",e._mathRandomGenerator()),e.setUniform1f("randomSeed2",e._mathRandomGenerator())},functionMatch:"Math.random()",functionReplace:"nrand(vTexCoord)",functionReturnType:"Number",source:"// https://www.shadertoy.com/view/4t2SDh\n//note: uniformly distributed, normalized rand, [0,1]\nhighp float randomSeedShift = 1.0;\nhighp float slide = 1.0;\nuniform highp float randomSeed1;\nuniform highp float randomSeed2;\n\nhighp float nrand(highp vec2 n) {\n highp float result = fract(sin(dot((n.xy + 1.0) * vec2(randomSeed1 * slide, randomSeed2 * randomSeedShift), vec2(12.9898, 78.233))) * 43758.5453);\n randomSeedShift = result;\n if (randomSeedShift > 0.5) {\n slide += 0.00009; \n } else {\n slide += 0.0009;\n }\n return result;\n}"}}),G=e((e,t)=>{t.exports={fragmentShader:`__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nvarying vec2 vTexCoord;\n\nfloat acosh(float x) {\n return log(x + sqrt(x * x - 1.0));\n}\n\nfloat sinh(float x) {\n return (pow(${Math.E}, x) - pow(${Math.E}, -x)) / 2.0;\n}\n\nfloat asinh(float x) {\n return log(x + sqrt(x * x + 1.0));\n}\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat atanh(float x) {\n x = (x + 1.0) / (x - 1.0);\n if (x < 0.0) {\n return 0.5 * log(-x);\n }\n return 0.5 * log(x);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat cosh(float x) {\n return (pow(${Math.E}, x) + pow(${Math.E}, -x)) / 2.0; \n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat tanh(float x) {\n float e = exp(2.0 * x);\n return (e - 1.0) / (e + 1.0);\n}\n\nfloat trunc(float x) {\n if (x >= 0.0) {\n return floor(x); \n } else {\n return ceil(x);\n }\n}\n\nvec4 _round(vec4 x) {\n return floor(x + 0.5);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x / y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(_round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(_round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n if (channel == 0) return texel.r * 255.0 + texel.g * 65280.0;\n if (channel == 1) return texel.b * 255.0 + texel.a * 65280.0;\n return 0.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n if (channel == 0) return texel.r * 255.0;\n if (channel == 1) return texel.g * 255.0;\n if (channel == 2) return texel.b * 255.0;\n if (channel == 3) return texel.a * 255.0;\n return 0.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return texel.r;\n if (channel == 1) return texel.g;\n if (channel == 2) return texel.b;\n if (channel == 3) return texel.a;\n return 0.0;\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture2D(tex, st / vec2(texSize));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture2D(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n \n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture2D(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture2D(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nvoid color(sampler2D image) {\n actualColor = texture2D(image, vTexCoord);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),V=e((e,t)=>{t.exports={vertexShader:"__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nattribute vec2 aPos;\nattribute vec2 aTexCoord;\n\nvarying vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),P=e((e,t)=>{function r(e,t={}){const{contextName:r="gl",throwGetError:a,useTrackablePrimitives:o,recording:u=[],variables:l={},onReadPixels:h,onUnrecognizedArgumentLookup:c}=t,p=new Proxy(e,{get:function(t,p){switch(p){case"addComment":return A;case"checkThrowError":return w;case"getReadPixelsVariableName":return m;case"insertVariable":return b;case"reset":return x;case"setIndent":return S;case"toString":return y;case"getContextVariableName":return E}return"function"==typeof e[p]?function(){switch(p){case"getError":return a?u.push(`${g}if (${r}.getError() !== ${r}.NONE) throw new Error('error');`):u.push(`${g}${r}.getError();`),e.getError();case"getExtension":{const t=`${r}Variables${d.length}`;u.push(`${g}const ${t} = ${r}.getExtension('${arguments[0]}');`);const n=e.getExtension(arguments[0]);if(n&&"object"==typeof n){const e=s(n,{getEntity:v,useTrackablePrimitives:o,recording:u,contextName:t,contextVariables:d,variables:l,indent:g,onUnrecognizedArgumentLookup:c});return d.push(e),e}return d.push(null),n}case"readPixels":const t=d.indexOf(arguments[6]);let i;if(-1===t){const e=function(e){if(l)for(const t in l)if(l[t]===e)return t;return null}(arguments[6]);e?(i=e,u.push(`${g}${e}`)):(i=`${r}Variable${d.length}`,d.push(arguments[6]),u.push(`${g}const ${i} = new ${arguments[6].constructor.name}(${arguments[6].length});`))}else i=`${r}Variable${t}`;m=i;const p=[arguments[0],arguments[1],arguments[2],arguments[3],v(arguments[4]),v(arguments[5]),i];return u.push(`${g}${r}.readPixels(${p.join(", ")});`),h&&h(i,p),e.readPixels.apply(e,arguments);case"drawBuffers":return u.push(`${g}${r}.drawBuffers([${n(arguments[0],{contextName:r,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})}]);`),e.drawBuffers(arguments[0])}let t=e[p].apply(e,arguments);switch(typeof t){case"undefined":return void u.push(`${g}${_(p,arguments)};`);case"number":case"boolean":if(o&&-1===d.indexOf(i(t))){u.push(`${g}const ${r}Variable${d.length} = ${_(p,arguments)};`),d.push(t=i(t));break}default:null===t?u.push(`${_(p,arguments)};`):u.push(`${g}const ${r}Variable${d.length} = ${_(p,arguments)};`),d.push(t)}return t}:(f[e[p]]=p,e[p])}}),d=[],f={};let m,g="";return p;function y(){return u.join("\n")}function x(){for(;u.length>0;)u.pop()}function b(e,t){l[e]=t}function v(e){const t=f[e];return t?r+"."+t:e}function S(e){g=" ".repeat(e)}function T(e,t){const s=`${r}Variable${d.length}`;return u.push(`${g}const ${s} = ${t};`),d.push(e),s}function A(e){u.push(`${g}// ${e}`)}function w(){u.push(`${g}(() => {\n${g}const error = ${r}.getError();\n${g}if (error !== ${r}.NONE) {\n${g} const names = Object.getOwnPropertyNames(gl);\n${g} for (let i = 0; i < names.length; i++) {\n${g} const name = names[i];\n${g} if (${r}[name] === error) {\n${g} throw new Error('${r} threw ' + name);\n${g} }\n${g} }\n${g}}\n${g}})();`)}function _(e,t){return`${r}.${e}(${n(t,{contextName:r,contextVariables:d,getEntity:v,addVariable:T,variables:l,onUnrecognizedArgumentLookup:c})})`}function E(e){const t=d.indexOf(e);return-1!==t?`${r}Variable${t}`:null}}function s(e,t){const r=new Proxy(e,{get:function(t,r){return"function"==typeof t[r]?function(){if("drawBuffersWEBGL"===r)return h.push(`${p}${a}.drawBuffersWEBGL([${n(arguments[0],{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})}]);`),e.drawBuffersWEBGL(arguments[0]);let t=e[r].apply(e,arguments);switch(typeof t){case"undefined":return void h.push(`${p}${m(r,arguments)};`);case"number":case"boolean":l&&-1===o.indexOf(i(t))?(h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t=i(t))):(h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t));break;default:null===t?h.push(`${m(r,arguments)};`):h.push(`${p}const ${a}Variable${o.length} = ${m(r,arguments)};`),o.push(t)}return t}:(s[e[r]]=r,e[r])}}),s={},{contextName:a,contextVariables:o,getEntity:u,useTrackablePrimitives:l,recording:h,variables:c,indent:p,onUnrecognizedArgumentLookup:d}=t;return r;function f(e){return s.hasOwnProperty(e)?`${a}.${s[e]}`:u(e)}function m(e,t){return`${a}.${e}(${n(t,{contextName:a,contextVariables:o,getEntity:f,addVariable:g,variables:c,onUnrecognizedArgumentLookup:d})})`}function g(e,t){const r=`${a}Variable${o.length}`;return o.push(e),h.push(`${p}const ${r} = ${t};`),r}}function n(e,t){const{variables:r,onUnrecognizedArgumentLookup:s}=t;return Array.from(e).map(e=>{const n=function(e){if(r)for(const t in r)if(r.hasOwnProperty(t)&&r[t]===e)return t;return s?s(e):null}(e);return n||function(e,t){const{contextName:r,contextVariables:s,getEntity:n,addVariable:i,onUnrecognizedArgumentLookup:a}=t;if(void 0===e)return"undefined";if(null===e)return"null";const o=s.indexOf(e);if(o>-1)return`${r}Variable${o}`;switch(e.constructor.name){case"String":const t=/\n/.test(e),r=/'/.test(e),s=/"/.test(e);return t?"`"+e+"`":r&&!s?'"'+e+'"':"'"+e+"'";case"Number":case"Boolean":return n(e);case"Array":return i(e,`new ${e.constructor.name}([${Array.from(e).join(",")}])`);case"Float32Array":case"Uint8Array":case"Uint16Array":case"Int32Array":return i(e,`new ${e.constructor.name}(${JSON.stringify(Array.from(e))})`);default:if(a){const t=a(e);if(t)return t}throw new Error(`unrecognized argument type ${e.constructor.name}`)}}(e,t)}).join(", ")}function i(e){return new e.constructor(e)}void 0!==t&&(t.exports={glWiretap:r,glExtensionWiretap:s}),"undefined"!=typeof window&&(r.glExtensionWiretap=s,window.glWiretap=r)}),B=e((e,t)=>{const{glWiretap:r}=P(),{utils:s}=i();function n(e){let t=e.toString().replace(/^function /,"");const r=t.indexOf("=>");if(-1!==r&&!/[{]|\bfunction\b/.test(t.slice(0,r))){const e=t.slice(0,r).trim(),s=t.slice(r+2).trim();t=s.startsWith("{")?`${e} ${s}`:`${e} { return ${s}; }`}return t.replace(/utils[.]/g,"/*utils.*/")}function a(e,t){const r="single"===t.precision?e:`new Float32Array(${e}.buffer)`;return t.output[2]?`renderOutput(${r}, ${t.output[0]}, ${t.output[1]}, ${t.output[2]})`:t.output[1]?`renderOutput(${r}, ${t.output[0]}, ${t.output[1]})`:`renderOutput(${r}, ${t.output[0]})`}function o(e,t){const r=e.toArray.toString(),n=!/^function/.test(r);return`() => {\n function framebuffer() { return getReadFramebuffer(); };\n ${s.flattenFunctionToString(`${n?"function ":""}${r}`,{findDependency:(t,r)=>{if("utils"===t)return`const ${r} = ${s[r].toString()};`;if("this"===t)return"framebuffer"===r?"":`${n?"function ":""}${e[r].toString()}`;throw new Error("unhandled fromObject")},thisLookup:(r,s)=>{if("texture"===r)return t;if("context"===r)return s?null:"gl";if(e.hasOwnProperty(r))return JSON.stringify(e[r]);throw new Error(`unhandled thisLookup ${r}`)}})}\n return toArray();\n }`}function u(e,t,r,s,n){if(null===e)return null;if(null===t)return null;switch(typeof e){case"boolean":case"number":return null}if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement)for(let n=0;n{switch(typeof e){case"boolean":return new Boolean(e);case"number":return new Number(e);default:return e}}):null;const c=[],p=[],d=r(i.context,{useTrackablePrimitives:!0,onReadPixels:e=>{if(N.subKernels){if(f){const t=N.subKernels[m++].property;p.push(` result${isNaN(t)?"."+t:`[${t}]`} = ${a(e,N)};`)}else p.push(` const result = { result: ${a(e,N)} };`),f=!0;m===N.subKernels.length&&p.push(" return result;")}else e?p.push(` return ${a(e,N)};`):p.push(" return null;")},onUnrecognizedArgumentLookup:e=>{const t=u(e,N.kernelArguments,[],d,c);if(t)return t;const r=u(e,N.kernelConstants,T?Object.keys(T).map(e=>T[e]):[],d,c);return r||null}});let f=!1,m=0;const{source:g,canvas:y,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:C,argumentTypes:L,constantTypes:D,kernelArguments:F,kernelConstants:$,tactic:R}=i,N=new e(g,{canvas:y,context:d,checkContext:!1,output:x,pipeline:b,graphical:v,loopMaxIterations:S,constants:T,optimizeFloatMemory:A,precision:w,fixIntegerDivisionAccuracy:_,functions:E,nativeFunctions:I,subKernels:k,immutable:C,argumentTypes:L,constantTypes:D,tactic:R});let M=[];if(d.setIndent(2),N.build.apply(N,t),M.push(d.toString()),d.reset(),N.kernelArguments.forEach((e,r)=>{switch(e.type){case"Integer":case"Boolean":case"Number":case"Float":case"Array":case"Array(2)":case"Array(3)":case"Array(4)":case"HTMLCanvas":case"HTMLImage":case"HTMLVideo":case"Input":d.insertVariable(`uploadValue_${e.name}`,e.uploadValue);break;case"HTMLImageArray":for(let s=0;se.varName).join(", ")}) {`),d.setIndent(4),N.run.apply(N,t),N.renderKernels?N.renderKernels():N.renderOutput&&N.renderOutput(),M.push(" /** start setup uploads for kernel values **/"),N.kernelArguments.forEach(e=>{M.push(" "+e.getStringValueHandler().split("\n").join("\n "))}),M.push(" /** end setup uploads for kernel values **/"),M.push(d.toString()),N.renderOutput===N.renderTexture)if(d.reset(),N.renderKernels){const e=N.renderKernels(),t=d.getContextVariableName(N.texture.texture);M.push(` return {\n result: {\n texture: ${t},\n type: '${e.result.type}',\n toArray: ${o(e.result,t)}\n },`);const{subKernels:r,mappedTextures:s}=N;for(let t=0;t"utils"===e?`const ${t} = ${s[t].toString()};`:null,thisLookup:t=>{if("context"===t)return null;if(e.hasOwnProperty(t))return JSON.stringify(e[t]);throw new Error(`unhandled thisLookup ${t}`)}})}(N)),M.push(" innerKernel.getPixels = getPixels;")),M.push(" return innerKernel;");let O=[];return $.forEach(e=>{O.push(`${e.getStringValueHandler()}`)}),`function kernel(settings) {\n const { context, constants } = settings;\n ${O.join("")}\n ${l||""}\n${M.join("\n")}\n}`}}}),z=e((e,t)=>{t.exports={KernelValue:class{constructor(e,t){const{name:r,kernel:s,context:n,checkContext:i,onRequestContextHandle:a,onUpdateValueMismatch:o,origin:u,strictIntegers:l,type:h,tactic:c}=t;if(!r)throw new Error("name not set");if(!h)throw new Error("type not set");if(!u)throw new Error("origin not set");if("user"!==u&&"constants"!==u)throw new Error(`origin must be "user" or "constants" value is "${u}"`);if(!a)throw new Error("onRequestContextHandle is not set");this.name=r,this.origin=u,this.tactic=c,this.varName="constants"===u?`constants.${r}`:r,this.kernel=s,this.strictIntegers=l,this.type=e.type||h,this.size=e.size||null,this.index=null,this.context=n,this.checkContext=null==i||i,this.contextHandle=null,this.onRequestContextHandle=a,this.onUpdateValueMismatch=o,this.forceUploadEachRun=null}get id(){return`${this.origin}_${name}`}getSource(){throw new Error(`"getSource" not defined on ${this.constructor.name}`)}updateValue(e){throw new Error(`"updateValue" not defined on ${this.constructor.name}`)}}}}),U=e((e,t)=>{const{utils:r}=i(),{KernelValue:s}=z();t.exports={WebGLKernelValue:class extends s{constructor(e,t){super(e,t),this.dimensionsId=null,this.sizeId=null,this.initialValueConstructor=e.constructor,this.onRequestTexture=t.onRequestTexture,this.onRequestIndex=t.onRequestIndex,this.uploadValue=null,this.textureSize=null,this.bitRatio=null,this.prevArg=null}get id(){return`${this.origin}_${r.sanitizeName(this.name)}`}setup(){}rebind(){}getTransferArrayType(e){if(Array.isArray(e[0]))return this.getTransferArrayType(e[0]);switch(e.constructor){case Array:case Int32Array:case Int16Array:case Int8Array:return Float32Array;case Uint8ClampedArray:case Uint8Array:case Uint16Array:case Uint32Array:case Float32Array:case Float64Array:return e.constructor}return console.warn("Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros"),e.constructor}getStringValueHandler(){throw new Error(`"getStringValueHandler" not implemented on ${this.constructor.name}`)}getVariablePrecisionString(){return this.kernel.getVariablePrecisionString(this.textureSize||void 0,this.tactic||void 0)}destroy(){}}}}),K=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:s}=U();t.exports={WebGLKernelValueBoolean:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const bool ${this.id} = ${e};\n`:`uniform bool ${this.id};\n`}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),W=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:s}=U();t.exports={WebGLKernelValueFloat:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?Number.isInteger(e)?`const float ${this.id} = ${r.glslFloatLiteral(e)};\n`:`const float ${this.id} = ${e};\n`:`uniform float ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1f(this.id,this.uploadValue=e)}}}}),j=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValue:s}=U();t.exports={WebGLKernelValueInteger:class extends s{constructor(e,t){super(e,t),this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(e){return"constants"===this.origin?`const int ${this.id} = ${parseInt(e)};\n`:`uniform int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),q=e((e,t)=>{const{WebGLKernelValue:r}=U(),{Input:n}=s();t.exports={WebGLKernelArray:class extends r{rebind(){if(!this.texture||void 0===this.contextHandle||null===this.contextHandle)return;const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D,this.texture)}checkSize(e,t){if(!this.kernel.validate)return;const{maxTextureSize:r}=this.kernel.constructor.features;if(e>r||t>r)throw e>t?new Error(`Argument texture width of ${e} larger than maximum size of ${r} for your GPU`):e{const{utils:r}=i(),{WebGLKernelArray:s}=q();function n(e){return{width:e.width>0?e.width:e.videoWidth,height:e.height>0?e.height:e.videoHeight}}t.exports={WebGLKernelValueHTMLImage:class extends s{constructor(e,t){super(e,t);const{width:r,height:s}=n(e);this.checkSize(r,s),this.dimensions=[r,s,1],this.textureSize=[r,s],this.uploadValue=e}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue=e),this.kernel.setUniform1i(this.id,this.index)}},mediaSize:n}}),H=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueHTMLImage:s,mediaSize:n}=X();t.exports={WebGLKernelValueDynamicHTMLImage:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:r}=n(e);this.checkSize(t,r),this.dimensions=[t,r,1],this.textureSize=[t,r],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Y=e((e,t)=>{const{WebGLKernelValueHTMLImage:r}=X();t.exports={WebGLKernelValueHTMLVideo:class extends r{}}}),Z=e((e,t)=>{const{WebGLKernelValueDynamicHTMLImage:r}=H();t.exports={WebGLKernelValueDynamicHTMLVideo:class extends r{}}}),J=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueSingleInput:class extends s{constructor(e,t){super(e,t),this.bitRatio=4;let[s,n,i]=e.size;this.dimensions=new Int32Array([s||1,n||1,i||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}.value, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Q=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleInput:s}=J();t.exports={WebGLKernelValueDynamicSingleInput:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,s,n]=e.size;this.dimensions=new Int32Array([t||1,s||1,n||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ee=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueUnsignedInput:class extends s{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e);const[s,n,i]=e.size;this.dimensions=new Int32Array([s||1,n||1,i||1]),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e.value),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return r.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}.value, preUploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(value.constructor);const{context:t}=this;r.flattenTo(e.value,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),te=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedInput:s}=ee();t.exports={WebGLKernelValueDynamicUnsignedInput:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,s,n]=e.size;this.dimensions=new Int32Array([t||1,s||1,n||1]),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const i=this.getTransferArrayType(e.value);this.preUploadValue=new i(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),re=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q(),n="Source and destination textures are the same. Use immutable = true and manually cleanup kernel output texture memory with texture.delete()";t.exports={WebGLKernelValueMemoryOptimizedNumberTexture:class extends s{constructor(e,t){super(e,t);const[r,s]=e.size;this.checkSize(r,s),this.dimensions=e.dimensions,this.textureSize=e.size,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:r}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(n);if(t.mappedTextures){const{mappedTextures:r}=t;for(let t=0;t{const{utils:r}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:s}=re();t.exports={WebGLKernelValueDynamicMemoryOptimizedNumberTexture:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ne=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q(),{sameError:n}=re();t.exports={WebGLKernelValueNumberTexture:class extends s{constructor(e,t){super(e,t);const[r,s]=e.size;this.checkSize(r,s);const{size:n,dimensions:i}=e;this.bitRatio=this.getBitRatio(e),this.dimensions=i,this.textureSize=n,this.uploadValue=e.texture,this.forceUploadEachRun=!0}setup(){this.setupTexture()}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName}.texture;\n`}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);if(this.checkContext&&e.context!==this.context)throw new Error(`Value ${this.name} (${this.type}) must be from same context`);const{kernel:t,context:r}=this;if(t.pipeline)if(t.immutable)t.updateTextureArgumentRefs(this,e);else{if(t.texture&&t.texture.texture===e.texture)throw new Error(n);if(t.mappedTextures){const{mappedTextures:r}=t;for(let t=0;t{const{utils:r}=i(),{WebGLKernelValueNumberTexture:s}=ne();t.exports={WebGLKernelValueDynamicNumberTexture:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=e.dimensions,this.checkSize(e.size[0],e.size[1]),this.textureSize=e.size,this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ae=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueSingleArray:class extends s{constructor(e,t){super(e,t),this.bitRatio=4,this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),oe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray:s}=ae();t.exports={WebGLKernelValueDynamicSingleArray:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),ue=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueSingleArray1DI:class extends s{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],1,1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten2dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),le=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray1DI:s}=ue();t.exports={WebGLKernelValueDynamicSingleArray1DI:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),he=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueSingleArray2DI:class extends s{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],1]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten3dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),ce=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray2DI:s}=he();t.exports={WebGLKernelValueDynamicSingleArray2DI:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),pe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueSingleArray3DI:class extends s{constructor(e,t){super(e,t),this.bitRatio=4,this.setShape(e)}setShape(e){const t=r.getDimensions(e,!0);this.textureSize=r.getMemoryOptimizedFloatTextureSize(t,this.bitRatio),this.dimensions=new Int32Array([t[1],t[2],t[3]]),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength)}getStringValueHandler(){return r.linesToString([`const uploadValue_${this.name} = new Float32Array(${this.uploadArrayLength})`,`flattenTo(${this.varName}, uploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flatten4dArrayTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),de=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray3DI:s}=pe();t.exports={WebGLKernelValueDynamicSingleArray3DI:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),fe=e((e,t)=>{const{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueArray2:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec2 ${this.id} = vec2(${e[0]},${e[1]});\n`:`uniform vec2 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform2fv(this.id,this.uploadValue=e)}}}}),me=e((e,t)=>{const{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueArray3:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec3 ${this.id} = vec3(${e[0]},${e[1]},${e[2]});\n`:`uniform vec3 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform3fv(this.id,this.uploadValue=e)}}}}),ge=e((e,t)=>{const{WebGLKernelValue:r}=U();t.exports={WebGLKernelValueArray4:class extends r{constructor(e,t){super(e,t),this.uploadValue=e}getSource(e){return"constants"===this.origin?`const vec4 ${this.id} = vec4(${e[0]},${e[1]},${e[2]},${e[3]});\n`:`uniform vec4 ${this.id};\n`}getStringValueHandler(){return"constants"===this.origin?"":`const uploadValue_${this.name} = ${this.varName};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform4fv(this.id,this.uploadValue=e)}}}}),ye=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGLKernelValueUnsignedArray:class extends s{constructor(e,t){super(e,t),this.bitRatio=this.getBitRatio(e),this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]),this.TranserArrayType=this.getTransferArrayType(e),this.preUploadValue=new this.TranserArrayType(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer)}getStringValueHandler(){return r.linesToString([`const preUploadValue_${this.name} = new ${this.TranserArrayType.name}(${this.uploadArrayLength})`,`const uploadValue_${this.name} = new Uint8Array(preUploadValue_${this.name}.buffer)`,`flattenTo(${this.varName}, preUploadValue_${this.name})`])}getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.preUploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.UNSIGNED_BYTE,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),xe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedArray:s}=ye();t.exports={WebGLKernelValueDynamicUnsignedArray:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedPackedTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*(4/this.bitRatio),this.checkSize(this.textureSize[0],this.textureSize[1]);const t=this.getTransferArrayType(e);this.preUploadValue=new t(this.uploadArrayLength),this.uploadValue=new Uint8Array(this.preUploadValue.buffer),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),be=e((e,t)=>{const{WebGLKernelValueBoolean:r}=K(),{WebGLKernelValueFloat:s}=W(),{WebGLKernelValueInteger:n}=j(),{WebGLKernelValueHTMLImage:i}=X(),{WebGLKernelValueDynamicHTMLImage:a}=H(),{WebGLKernelValueHTMLVideo:o}=Y(),{WebGLKernelValueDynamicHTMLVideo:u}=Z(),{WebGLKernelValueSingleInput:l}=J(),{WebGLKernelValueDynamicSingleInput:h}=Q(),{WebGLKernelValueUnsignedInput:c}=ee(),{WebGLKernelValueDynamicUnsignedInput:p}=te(),{WebGLKernelValueMemoryOptimizedNumberTexture:d}=re(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:f}=se(),{WebGLKernelValueNumberTexture:m}=ne(),{WebGLKernelValueDynamicNumberTexture:g}=ie(),{WebGLKernelValueSingleArray:y}=ae(),{WebGLKernelValueDynamicSingleArray:x}=oe(),{WebGLKernelValueSingleArray1DI:b}=ue(),{WebGLKernelValueDynamicSingleArray1DI:v}=le(),{WebGLKernelValueSingleArray2DI:S}=he(),{WebGLKernelValueDynamicSingleArray2DI:T}=ce(),{WebGLKernelValueSingleArray3DI:A}=pe(),{WebGLKernelValueDynamicSingleArray3DI:w}=de(),{WebGLKernelValueArray2:_}=fe(),{WebGLKernelValueArray3:E}=me(),{WebGLKernelValueArray4:I}=ge(),{WebGLKernelValueUnsignedArray:k}=ye(),{WebGLKernelValueDynamicUnsignedArray:C}=xe(),L={unsigned:{dynamic:{Boolean:r,Integer:n,Float:s,Array:C,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:p,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:r,Float:s,Integer:n,Array:k,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:c,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}},single:{dynamic:{Boolean:r,Integer:n,Float:s,Array:x,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":v,"Array1D(3)":v,"Array1D(4)":v,"Array2D(2)":T,"Array2D(3)":T,"Array2D(4)":T,"Array3D(2)":w,"Array3D(3)":w,"Array3D(4)":w,Input:h,NumberTexture:g,"ArrayTexture(1)":g,"ArrayTexture(2)":g,"ArrayTexture(3)":g,"ArrayTexture(4)":g,MemoryOptimizedNumberTexture:f,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:!1,HTMLVideo:u},static:{Boolean:r,Float:s,Integer:n,Array:y,"Array(2)":_,"Array(3)":E,"Array(4)":I,"Array1D(2)":b,"Array1D(3)":b,"Array1D(4)":b,"Array2D(2)":S,"Array2D(3)":S,"Array2D(4)":S,"Array3D(2)":A,"Array3D(3)":A,"Array3D(4)":A,Input:l,NumberTexture:m,"ArrayTexture(1)":m,"ArrayTexture(2)":m,"ArrayTexture(3)":m,"ArrayTexture(4)":m,MemoryOptimizedNumberTexture:d,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:!1,HTMLVideo:o}}};t.exports={lookupKernelValueType:function(e,t,r,s){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!r)throw new Error("precision missing");s.type&&(e=s.type);const n=L[r][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===n[e])return null;if(void 0===n[e])throw new Error(`Could not find a KernelValue for ${e}`);return n[e]},kernelValueMaps:L}}),ve=e((e,t)=>{const{GLKernel:r}=N(),{FunctionBuilder:s}=u(),{WebGLFunctionNode:n}=M(),{utils:a}=i(),o=O(),{fragmentShader:l}=G(),{vertexShader:h}=V(),{glKernelString:c}=B(),{lookupKernelValueType:p}=be();let d=null,f=null,m=null,g=null,y=null;const x=[o],b=[],v={};t.exports={WebGLKernel:class extends r{static get isSupported(){return null!==d||(this.setupFeatureChecks(),d=this.isContextMatch(m)),d}static setupFeatureChecks(){"undefined"!=typeof document?f=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(f=new OffscreenCanvas(0,0)),f&&(m=f.getContext("webgl"),m||f instanceof OffscreenCanvas||(m=f.getContext("experimental-webgl")),m&&m.getExtension&&(g={OES_texture_float:m.getExtension("OES_texture_float"),OES_texture_float_linear:m.getExtension("OES_texture_float_linear"),OES_element_index_uint:m.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:m.getExtension("WEBGL_draw_buffers")},y=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGLRenderingContext&&e instanceof WebGLRenderingContext}static getIsTextureFloat(){return Boolean(g.OES_texture_float)}static getIsDrawBuffers(){return Boolean(g.WEBGL_draw_buffers)}static getChannelCount(){return g.WEBGL_draw_buffers?m.getParameter(g.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return m.getParameter(m.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,r,s){return p(e,t,r,s)}static get testCanvas(){return f}static get testContext(){return m}static get features(){return y}static get fragmentShader(){return l}static get vertexShader(){return h}constructor(e,t){super(e,t),this.program=null,this.pipeline=t.pipeline,this.endianness=a.systemEndianness(),this.extensions={},this.argumentTextureCount=0,this.constantTextureCount=0,this.fragShader=null,this.vertShader=null,this.drawBuffersMap=null,this.maxTexSize=null,this.onRequestSwitchKernel=null,this.texture=null,this.mappedTextures=null,this.mergeSettings(e.settings||t),this.threadDim=null,this.framebuffer=null,this.buffer=null,this.textureCache=[],this.programUniformLocationCache={},this.uniform1fCache={},this.uniform1iCache={},this.uniform2fCache={},this.uniform2fvCache={},this.uniform2ivCache={},this.uniform3fvCache={},this.uniform3ivCache={},this.uniform4fvCache={},this.uniform4ivCache={}}initCanvas(){if("undefined"!=typeof document){const e=document.createElement("canvas");return e.width=2,e.height=2,e}if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(0,0)}initContext(){const e={alpha:!1,depth:!1,antialias:!1};return this.canvas.getContext("webgl",e)||this.canvas.getContext("experimental-webgl",e)}pluginMatchSource(){if("string"!=typeof this.source)return null;if(!this.functions||this.functions.length<1)return this.source;const e=[this.source];for(let t=0;te===s.name)&&t.push(s)}return t}initExtensions(){this.extensions={OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:this.context.getExtension("WEBGL_color_buffer_float")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if(!0===this.optimizeFloatMemory&&!t.isTextureFloat)throw new Error("Float textures are not supported");if("single"===this.precision&&!t.isFloatRead)throw new Error("Single precision not supported");if(this.graphical||null!==this.precision||(this.precision=t.isTextureFloat&&t.isFloatRead?"single":"unsigned"),this.subKernels&&this.subKernels.length>0&&!this.extensions.WEBGL_draw_buffers)throw new Error("could not instantiate draw buffers extension");if(null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"precision"===this.precision&&(this.precision="unsigned",console.warn("Cannot use graphical mode and single precision at the same time")),void(this.texSize=a.clone(this.output))}null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}updateMaxTexSize(){const{texSize:e,canvas:t}=this;if(null===this.maxTexSize){let r=b.indexOf(t);-1===r&&(r=b.length,b.push(t),v[r]=[e[0],e[1]]),this.maxTexSize=v[r]}this.maxTexSize[0]this.argumentNames.length)throw new Error("too many arguments for kernel");const{context:r}=this;let s=0;const n=()=>this.createTexture(),i=()=>this.constantTextureCount+s++,o=e=>{this.switchKernels({type:"argumentMismatch",needed:e})},u=()=>r.TEXTURE0+this.constantTextureCount+this.argumentTextureCount++;for(let s=0;sthis.createTexture(),onRequestIndex:()=>s++,onRequestContextHandle:()=>t.TEXTURE0+this.constantTextureCount++});this.constantBitRatios[n]=l.bitRatio,this.kernelConstants.push(l),l.setup(),l.forceUploadEachRun&&this.forceUploadKernelConstants.push(l)}}build(){if(this.built)return;if(this.initExtensions(),this.validateSettings(arguments),this.setupConstants(arguments),this.fallbackRequested)return;if(this.setupArguments(arguments),this.fallbackRequested)return;this.updateMaxTexSize(),this.buildWithOptimizer(()=>this.translateSource());const e=this.pickRenderStrategy(arguments);if(e)return e;const{texSize:t,context:r,canvas:s}=this;r.enable(r.SCISSOR_TEST),this.pipeline&&this.precision,r.viewport(0,0,this.maxTexSize[0],this.maxTexSize[1]),s.width=this.maxTexSize[0],s.height=this.maxTexSize[1];const n=this.threadDim=Array.from(this.output);for(;n.length<3;)n.push(1);const i=this.getVertexShader(arguments),a=r.createShader(r.VERTEX_SHADER);r.shaderSource(a,i),r.compileShader(a),this.vertShader=a;const o=this.getFragmentShader(arguments),u=r.createShader(r.FRAGMENT_SHADER);if(r.shaderSource(u,o),r.compileShader(u),this.fragShader=u,this.debug&&(console.log("GLSL Shader Output:"),console.log(o)),!r.getShaderParameter(a,r.COMPILE_STATUS))throw new Error("Error compiling vertex shader: "+r.getShaderInfoLog(a));if(!r.getShaderParameter(u,r.COMPILE_STATUS))throw new Error("Error compiling fragment shader: "+r.getShaderInfoLog(u));const l=this.program=r.createProgram();r.attachShader(l,a),r.attachShader(l,u),r.linkProgram(l),this.framebuffer=r.createFramebuffer(),this.framebuffer.width=t[0],this.framebuffer.height=t[1],this.rawValueFramebuffers={};const h=new Float32Array([-1,-1,1,-1,-1,1,1,1]),c=new Float32Array([0,0,1,0,0,1,1,1]),p=h.byteLength;let d=this.buffer;d?r.bindBuffer(r.ARRAY_BUFFER,d):(d=this.buffer=r.createBuffer(),r.bindBuffer(r.ARRAY_BUFFER,d),r.bufferData(r.ARRAY_BUFFER,h.byteLength+c.byteLength,r.STATIC_DRAW)),r.bufferSubData(r.ARRAY_BUFFER,0,h),r.bufferSubData(r.ARRAY_BUFFER,p,c);const f=r.getAttribLocation(this.program,"aPos");-1!==f&&(r.enableVertexAttribArray(f),r.vertexAttribPointer(f,2,r.FLOAT,!1,0,0));const m=r.getAttribLocation(this.program,"aTexCoord");-1!==m&&(r.enableVertexAttribArray(m),r.vertexAttribPointer(m,2,r.FLOAT,!1,0,p)),r.bindFramebuffer(r.FRAMEBUFFER,this.framebuffer);let g=0;r.useProgram(this.program);for(let e in this.constants)this.kernelConstants[g++].updateValue(this.constants[e]);this._setupOutputTexture(),null!==this.subKernels&&this.subKernels.length>0&&(this._mappedTextureSwitched={},this._setupSubOutputTextures()),this.buildSignature(arguments),this.built=!0}translateSource(){const e=s.fromKernel(this,n,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}setupReturnTypes(e){if(this.graphical||this.returnType||(this.returnType=e.getKernelResultType()),this.subKernels&&this.subKernels.length>0)for(let t=0;tt.source&&e.match(t.functionMatch)?t.source:"").join("\n")}_getConstantsString(){const e=[],{threadDim:t,texSize:r}=this;return this.dynamicOutput?e.push("uniform ivec3 uOutputDim","uniform ivec2 uTexSize"):e.push(`ivec3 uOutputDim = ivec3(${t[0]}, ${t[1]}, ${t[2]})`,`ivec2 uTexSize = ivec2(${r[0]}, ${r[1]})`),a.linesToString(e)}_getTextureCoordinate(){const e=this.subKernels;return null===e||e.length<1?"varying vec2 vTexCoord;\n":"out vec2 vTexCoord;\n"}_getDecode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getEncode32EndiannessString(){return"LE"===this.endianness?"":" texel.rgba = texel.abgr;\n"}_getDivideWithIntegerCheckString(){return this.fixIntegerDivisionAccuracy?"float divWithIntCheck(float x, float y) {\n if (floor(x) == x && floor(y) == y) {\n float q = floor(x / y + 0.5);\n if (y * q == x) {\n return q;\n }\n }\n return x / y;\n}\n\nfloat integerCorrectionModulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -(number - (divisor * floor(divWithIntCheck(number, divisor))));\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return number - (divisor * floor(divWithIntCheck(number, divisor)));\n}":""}_getMainArgumentsString(e){const t=[],{argumentNames:r}=this;for(let s=0;s{if(t.hasOwnProperty(r))return t[r];throw`unhandled artifact ${r}`})}getFragmentShader(e){return null!==this.compiledFragmentShader?this.compiledFragmentShader:this.compiledFragmentShader=this.replaceArtifacts(this.constructor.fragmentShader,this._getFragShaderArtifactMap(e))}getVertexShader(e){return null!==this.compiledVertexShader?this.compiledVertexShader:this.compiledVertexShader=this.replaceArtifacts(this.constructor.vertexShader,this._getVertShaderArtifactMap(e))}toString(){const e=a.linesToString(["const gl = context"]);return c(this.constructor,arguments,this,e)}destroy(e){if(!this.context)return;this.buffer&&this.context.deleteBuffer(this.buffer),this.framebuffer&&this.context.deleteFramebuffer(this.framebuffer);for(const e in this.rawValueFramebuffers){for(const t in this.rawValueFramebuffers[e])this.context.deleteFramebuffer(this.rawValueFramebuffers[e][t]),delete this.rawValueFramebuffers[e][t];delete this.rawValueFramebuffers[e]}if(this.vertShader&&this.context.deleteShader(this.vertShader),this.fragShader&&this.context.deleteShader(this.fragShader),this.program&&this.context.deleteProgram(this.program),this.texture){this.texture.delete();const e=this.textureCache.indexOf(this.texture.texture);e>-1&&this.textureCache.splice(e,1),this.texture=null}if(this.mappedTextures&&this.mappedTextures.length){for(let e=0;e-1&&this.textureCache.splice(r,1)}this.mappedTextures=null}if(this.kernelArguments)for(let e=0;e0;){const e=this.textureCache.pop();this.context.deleteTexture(e)}if(e){const e=b.indexOf(this.canvas);e>=0&&(b[e]=null,v[e]=null)}if(this.destroyExtensions(),delete this.context,delete this.canvas,!this.gpu)return;const t=this.gpu.kernels.indexOf(this);-1!==t&&this.gpu.kernels.splice(t,1)}destroyExtensions(){this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("WEBGL_lose_context");t&&t.loseContext()}toJSON(){const e=super.toJSON();return e.functionNodes=s.fromKernel(this,n).toJSON(),e.settings.threadDim=this.threadDim,e}}}}),Se=e((e,t)=>{const r=f(),{WebGLKernel:s}=ve(),{glKernelString:n}=B();let i=null,a=null,o=null,u=null,l=null;t.exports={HeadlessGLKernel:class extends s{static get isSupported(){return null!==i||(this.setupFeatureChecks(),i=null!==o),i}static setupFeatureChecks(){if(a=null,u=null,"function"==typeof r)try{if(o=r(2,2,{preserveDrawingBuffer:!0}),!o||!o.getExtension)return;u={STACKGL_resize_drawingbuffer:o.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:o.getExtension("STACKGL_destroy_context"),OES_texture_float:o.getExtension("OES_texture_float"),OES_texture_float_linear:o.getExtension("OES_texture_float_linear"),OES_element_index_uint:o.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:o.getExtension("WEBGL_draw_buffers"),WEBGL_color_buffer_float:o.getExtension("WEBGL_color_buffer_float")},l=this.getFeatures()}catch(e){console.warn(e)}}static isContextMatch(e){try{return"ANGLE"===e.getParameter(e.RENDERER)}catch(e){return!1}}static getIsTextureFloat(){return Boolean(u.OES_texture_float)}static getIsDrawBuffers(){return Boolean(u.WEBGL_draw_buffers)}static getChannelCount(){return u.WEBGL_draw_buffers?o.getParameter(u.WEBGL_draw_buffers.MAX_DRAW_BUFFERS_WEBGL):1}static getMaxTextureSize(){return o.getParameter(o.MAX_TEXTURE_SIZE)}static get testCanvas(){return a}static get testContext(){return o}static get features(){return l}initCanvas(){return{}}initContext(){return r(2,2,{preserveDrawingBuffer:!0})}initExtensions(){this.extensions={STACKGL_resize_drawingbuffer:this.context.getExtension("STACKGL_resize_drawingbuffer"),STACKGL_destroy_context:this.context.getExtension("STACKGL_destroy_context"),OES_texture_float:this.context.getExtension("OES_texture_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear"),OES_element_index_uint:this.context.getExtension("OES_element_index_uint"),WEBGL_draw_buffers:this.context.getExtension("WEBGL_draw_buffers")}}build(){super.build.apply(this,arguments),this.fallbackRequested||this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1])}destroyExtensions(){this.extensions.STACKGL_resize_drawingbuffer=null,this.extensions.STACKGL_destroy_context=null,this.extensions.OES_texture_float=null,this.extensions.OES_texture_float_linear=null,this.extensions.OES_element_index_uint=null,this.extensions.WEBGL_draw_buffers=null}static destroyContext(e){const t=e.getExtension("STACKGL_destroy_context");t&&t.destroy&&t.destroy()}toString(){return n(this.constructor,arguments,this,"const gl = context || require('gl')(1, 1);\n"," if (!context) { gl.getExtension('STACKGL_destroy_context').destroy(); }\n")}setOutput(e){return super.setOutput(e),this.graphical&&this.extensions.STACKGL_resize_drawingbuffer&&this.extensions.STACKGL_resize_drawingbuffer.resize(this.maxTexSize[0],this.maxTexSize[1]),this}}}}),Te=e((e,t)=>{const{utils:r}=i(),{WebGLFunctionNode:s}=M();t.exports={WebGL2FunctionNode:class extends s{astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const s=this.getType(e),n=r.sanitizeName(e.name);if("Infinity"===e.name)t.push("intBitsToFloat(2139095039)");else if("Boolean"===s)if(this.argumentNames.indexOf(n)>-1){const r=this.markupUserName(e.name);t.push(r.startsWith("cellShadow_")?r:`bool(${r})`)}else t.push(`user_${n}`);else t.push(this.markupUserName(e.name));return t}}}}),Ae=e((e,t)=>{t.exports={fragmentShader:`#version 300 es\n__HEADER__;\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n__SAMPLER_2D_ARRAY_TACTIC_DECLARATION__;\n\nconst int LOOP_MAX = __LOOP_MAX__;\n\n__PLUGINS__;\n__CONSTANTS__;\n\nin vec2 vTexCoord;\n\nfloat atan2(float v1, float v2) {\n if (v2 == 0.0) {\n if (v1 == 0.0) return 0.0;\n if (v1 > 0.0) return 1.5707963267948966;\n if (v1 < 0.0) return -1.5707963267948966;\n }\n return atan(v1, v2);\n}\n\nfloat cbrt(float x) {\n if (x >= 0.0) {\n return pow(x, 1.0 / 3.0);\n } else {\n return -pow(x, 1.0 / 3.0);\n }\n}\n\nfloat expm1(float x) {\n return pow(${Math.E}, x) - 1.0; \n}\n\nfloat fround(highp float x) {\n return x;\n}\n\nfloat imul(float v1, float v2) {\n return float(int(v1) * int(v2));\n}\n\nfloat log10(float x) {\n return log2(x) * (1.0 / log2(10.0));\n}\n\nfloat log1p(float x) {\n return log(1.0 + x);\n}\n\nfloat _pow(float v1, float v2) {\n if (v2 == 0.0) return 1.0;\n return pow(v1, v2);\n}\n\nfloat _round(float x) {\n return floor(x + 0.5);\n}\n\n\nconst int BIT_COUNT = 32;\nint modi(int x, int y) {\n return x - y * (x / y);\n}\n\nint bitwiseOr(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) || (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseXOR(int a, int b) {\n int result = 0;\n int n = 1;\n \n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) != (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 || b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseAnd(int a, int b) {\n int result = 0;\n int n = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if ((modi(a, 2) == 1) && (modi(b, 2) == 1)) {\n result += n;\n }\n a = a / 2;\n b = b / 2;\n n = n * 2;\n if(!(a > 0 && b > 0)) {\n break;\n }\n }\n return result;\n}\nint bitwiseNot(int a) {\n // ~a is identically -a - 1 in two's complement, for every value including\n // negatives. The previous bit-by-bit loop only worked for a >= 0, where it\n // leaned on 32-bit overflow wrapping to reach the negative answer; given a\n // negative input it computed ~abs(a), so ~(-1) gave -2 and ~~x never\n // returned x.\n return -a - 1;\n}\nint bitwiseZeroFillLeftShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n *= 2;\n }\n\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\n// _pow2 is defined further down, alongside encode32/decode32\nfloat _pow2(float e);\nint bitwiseSignedRightShift(int num, int shifts) {\n // pow(2.0, n) is approximate on many GPUs, and landing 1 ulp high makes the\n // division fall just under a whole number, which floor() then rounds away:\n // 2 >> 1 came out 0, 8 >> 1 came out 3. Only exact left operands were\n // affected, odd ones having enough slack to survive. _pow2 is exact.\n return int(floor(float(num) / _pow2(float(shifts))));\n}\n\nint bitwiseZeroFillRightShift(int n, int shift) {\n int maxBytes = BIT_COUNT;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (maxBytes >= n) {\n break;\n }\n maxBytes *= 2;\n }\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= shift) {\n break;\n }\n n /= 2;\n }\n int result = 0;\n int byteVal = 1;\n for (int i = 0; i < BIT_COUNT; i++) {\n if (i >= maxBytes) break;\n if (modi(n, 2) > 0) { result += byteVal; }\n n = int(n / 2);\n byteVal *= 2;\n }\n return result;\n}\n\nvec2 integerMod(vec2 x, float y) {\n vec2 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec3 integerMod(vec3 x, float y) {\n vec3 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nvec4 integerMod(vec4 x, vec4 y) {\n vec4 res = floor(mod(x, y));\n return res * step(1.0 - floor(y), -res);\n}\n\nfloat integerMod(float x, float y) {\n float res = floor(mod(x, y));\n return res * (res > floor(y) - 1.0 ? 0.0 : 1.0);\n}\n\nint integerMod(int x, int y) {\n return x - (y * int(x/y));\n}\n\n// GLSL ES 1.00 accepts only a constant or a loop symbol inside an index\n// expression, so m[y][x] does not compile when y and x come from kernel\n// arguments -- the error is "Index expression can only contain const or loop\n// symbols". Loop counters are legal indices, so walk the matrix with them\n// instead. These are 2x2 to 4x4, so it costs at most sixteen comparisons.\nfloat getMatrix2(mat2 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 2; i++) {\n for (int j = 0; j < 2; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix3(mat3 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 3; i++) {\n for (int j = 0; j < 3; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\nfloat getMatrix4(mat4 m, int y, int x) {\n float result = 0.0;\n for (int i = 0; i < 4; i++) {\n for (int j = 0; j < 4; j++) {\n if (i == y && j == x) result = m[i][j];\n }\n }\n return result;\n}\n\n__DIVIDE_WITH_INTEGER_CHECK__;\n\n// Here be dragons!\n// DO NOT OPTIMIZE THIS CODE\n// YOU WILL BREAK SOMETHING ON SOMEBODY'S MACHINE\n// LEAVE IT AS IT IS, LEST YOU WASTE YOUR OWN TIME\n// Exact powers of two built from exact constant multiplies: exp2/log2/pow\n// are approximate on some GPUs (notably Apple silicon), and 1-2 ulp there\n// corrupts the packed bytes (#659)\nfloat _pow2(float e) {\n float r = 1.0;\n float a = abs(e);\n bool n = e < 0.0;\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 64.0) { r *= n ? 5.421010862427522e-20 : 18446744073709551616.0; a -= 64.0; }\n if (a >= 32.0) { r *= n ? 2.3283064365386963e-10 : 4294967296.0; a -= 32.0; }\n if (a >= 16.0) { r *= n ? 0.0000152587890625 : 65536.0; a -= 16.0; }\n if (a >= 8.0) { r *= n ? 0.00390625 : 256.0; a -= 8.0; }\n if (a >= 4.0) { r *= n ? 0.0625 : 16.0; a -= 4.0; }\n if (a >= 2.0) { r *= n ? 0.25 : 4.0; a -= 2.0; }\n if (a >= 1.0) { r *= n ? 0.5 : 2.0; }\n return r;\n}\nconst vec2 MAGIC_VEC = vec2(1.0, -256.0);\nconst vec4 SCALE_FACTOR = vec4(1.0, 256.0, 65536.0, 0.0);\nconst vec4 SCALE_FACTOR_INV = vec4(1.0, 0.00390625, 0.0000152587890625, 0.0); // 1, 1/256, 1/65536\nfloat decode32(vec4 texel) {\n __DECODE32_ENDIANNESS__;\n texel *= 255.0;\n vec2 gte128;\n gte128.x = texel.b >= 128.0 ? 1.0 : 0.0;\n gte128.y = texel.a >= 128.0 ? 1.0 : 0.0;\n float exponent = 2.0 * texel.a - 127.0 + dot(gte128, MAGIC_VEC);\n float res = _pow2(round(exponent));\n texel.b = texel.b - 128.0 * gte128.x;\n res = dot(texel, SCALE_FACTOR) * _pow2(round(exponent-23.0)) + res;\n res *= gte128.y * -2.0 + 1.0;\n return res;\n}\n\nfloat decode16(vec4 texel, int index) {\n int channel = integerMod(index, 2);\n return texel[channel*2] * 255.0 + texel[channel*2 + 1] * 65280.0;\n}\n\nfloat decode8(vec4 texel, int index) {\n int channel = integerMod(index, 4);\n return texel[channel] * 255.0;\n}\n\nvec4 legacyEncode32(float f) {\n float F = abs(f);\n float sign = f < 0.0 ? 1.0 : 0.0;\n float exponent = floor(log2(F));\n float mantissa = (exp2(-exponent) * F);\n // exponent += floor(log2(mantissa));\n vec4 texel = vec4(F * exp2(23.0-exponent)) * SCALE_FACTOR_INV;\n texel.rg = integerMod(texel.rg, 256.0);\n texel.b = integerMod(texel.b, 128.0);\n texel.a = exponent*0.5 + 63.5;\n texel.ba += vec2(integerMod(exponent+127.0, 2.0), sign) * 128.0;\n texel = floor(texel);\n texel *= 0.003921569; // 1/255\n __ENCODE32_ENDIANNESS__;\n return texel;\n}\n\n// https://github.com/gpujs/gpu.js/wiki/Encoder-details\nvec4 encode32(float value) {\n if (value == 0.0) return vec4(0, 0, 0, 0);\n\n float exponent;\n float mantissa;\n vec4 result;\n float sgn;\n\n sgn = step(0.0, -value);\n value = abs(value);\n\n exponent = floor(log2(value));\n float p2 = _pow2(exponent);\n // approximate log2 can land one off; correct by direct comparison\n if (p2 > value) { exponent -= 1.0; p2 *= 0.5; }\n else if (p2 * 2.0 <= value) { exponent += 1.0; p2 *= 2.0; }\n\n mantissa = value / p2 - 1.0;\n exponent = exponent+127.0;\n result = vec4(0,0,0,0);\n\n result.a = floor(exponent/2.0);\n exponent = exponent - result.a*2.0;\n result.a = result.a + 128.0*sgn;\n\n result.b = floor(mantissa * 128.0);\n mantissa = mantissa - result.b / 128.0;\n result.b = result.b + exponent*128.0;\n\n result.g = floor(mantissa*32768.0);\n mantissa = mantissa - result.g/32768.0;\n\n result.r = floor(mantissa*8388608.0);\n return result/255.0;\n}\n// Dragons end here\n\nint index;\nivec3 threadId;\n\nivec3 indexTo3D(int idx, ivec3 texDim) {\n int z = int(idx / (texDim.x * texDim.y));\n idx -= z * int(texDim.x * texDim.y);\n int y = int(idx / texDim.x);\n int x = int(integerMod(idx, texDim.x));\n return ivec3(x, y, z);\n}\n\nfloat get32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return decode32(texel);\n}\n\nfloat get16(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 2;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 2, texSize.y));\n return decode16(texel, index);\n}\n\nfloat get8(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int w = texSize.x * 4;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize.x * 4, texSize.y));\n return decode8(texel, index);\n}\n\nfloat getMemoryOptimized32(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + (texDim.x * (y + (texDim.y * z)));\n int channel = integerMod(index, 4);\n index = index / 4;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n index = index / 4;\n vec4 texel = texture(tex, st / vec2(texSize));\n return texel[channel];\n}\n\nvec4 getImage2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, st / vec2(texSize));\n}\n\nvec4 getImage3D(sampler2DArray tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n return texture(tex, vec3(st / vec2(texSize), z));\n}\n\nfloat getFloatFromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return result[0];\n}\n\nvec2 getVec2FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec2(result[0], result[1]);\n}\n\nvec2 getMemoryOptimizedVec2(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n index = index / 2;\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n if (channel == 0) return vec2(texel.r, texel.g);\n if (channel == 1) return vec2(texel.b, texel.a);\n return vec2(0.0, 0.0);\n}\n\nvec3 getVec3FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n vec4 result = getImage2D(tex, texSize, texDim, z, y, x);\n return vec3(result[0], result[1], result[2]);\n}\n\nvec3 getMemoryOptimizedVec3(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int fieldIndex = 3 * (x + texDim.x * (y + texDim.y * z));\n int vectorIndex = fieldIndex / 4;\n int vectorOffset = fieldIndex - vectorIndex * 4;\n int readY = vectorIndex / texSize.x;\n int readX = vectorIndex - readY * texSize.x;\n vec4 tex1 = texture(tex, (vec2(readX, readY) + 0.5) / vec2(texSize));\n\n if (vectorOffset == 0) {\n return tex1.xyz;\n } else if (vectorOffset == 1) {\n return tex1.yzw;\n } else {\n readX++;\n if (readX >= texSize.x) {\n readX = 0;\n readY++;\n }\n vec4 tex2 = texture(tex, vec2(readX, readY) / vec2(texSize));\n if (vectorOffset == 2) {\n return vec3(tex1.z, tex1.w, tex2.x);\n } else {\n return vec3(tex1.w, tex2.x, tex2.y);\n }\n }\n}\n\nvec4 getVec4FromSampler2D(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n return getImage2D(tex, texSize, texDim, z, y, x);\n}\n\nvec4 getMemoryOptimizedVec4(sampler2D tex, ivec2 texSize, ivec3 texDim, int z, int y, int x) {\n int index = x + texDim.x * (y + texDim.y * z);\n int channel = integerMod(index, 2);\n int w = texSize.x;\n vec2 st = vec2(float(integerMod(index, w)), float(index / w)) + 0.5;\n vec4 texel = texture(tex, st / vec2(texSize));\n return vec4(texel.r, texel.g, texel.b, texel.a);\n}\n\nvec4 actualColor;\nvoid color(float r, float g, float b, float a) {\n actualColor = vec4(r,g,b,a);\n}\n\nvoid color(float r, float g, float b) {\n color(r,g,b,1.0);\n}\n\nfloat modulo(float number, float divisor) {\n if (number < 0.0) {\n number = abs(number);\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return -mod(number, divisor);\n }\n if (divisor < 0.0) {\n divisor = abs(divisor);\n }\n return mod(number, divisor);\n}\n\n__INJECTED_NATIVE__;\n__MAIN_CONSTANTS__;\n__MAIN_ARGUMENTS__;\n__KERNEL__;\n\nvoid main(void) {\n index = int(vTexCoord.s * float(uTexSize.x)) + int(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;\n __MAIN_RESULT__;\n}`}}),we=e((e,t)=>{t.exports={vertexShader:"#version 300 es\n__FLOAT_TACTIC_DECLARATION__;\n__INT_TACTIC_DECLARATION__;\n__SAMPLER_2D_TACTIC_DECLARATION__;\n\nin vec2 aPos;\nin vec2 aTexCoord;\n\nout vec2 vTexCoord;\nuniform vec2 ratio;\n\nvoid main(void) {\n gl_Position = vec4((aPos + vec2(1)) * ratio + vec2(-1), 0, 1);\n vTexCoord = aTexCoord;\n}"}}),_e=e((e,t)=>{const{WebGLKernelValueBoolean:r}=K();t.exports={WebGL2KernelValueBoolean:class extends r{}}}),Ee=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueFloat:s}=W();t.exports={WebGL2KernelValueFloat:class extends s{}}}),Ie=e((e,t)=>{const{WebGLKernelValueInteger:r}=j();t.exports={WebGL2KernelValueInteger:class extends r{getSource(e){const t=this.getVariablePrecisionString();return"constants"===this.origin?`const ${t} int ${this.id} = ${parseInt(e)};\n`:`uniform ${t} int ${this.id};\n`}updateValue(e){"constants"!==this.origin&&this.kernel.setUniform1i(this.id,this.uploadValue=e)}}}}),ke=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueHTMLImage:s}=X();t.exports={WebGL2KernelValueHTMLImage:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Ce=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicHTMLImage:s}=H();t.exports={WebGL2KernelValueDynamicHTMLImage:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Le=e((e,t)=>{const{utils:r}=i(),{WebGLKernelArray:s}=q();t.exports={WebGL2KernelValueHTMLImageArray:class extends s{constructor(e,t){super(e,t),this.checkSize(e[0].width,e[0].height),this.dimensions=[e[0].width,e[0].height,e.length],this.textureSize=[e[0].width,e[0].height]}defineTexture(){const{context:e}=this;e.activeTexture(this.contextHandle),e.bindTexture(e.TEXTURE_2D_ARRAY,this.texture),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D_ARRAY,e.TEXTURE_MIN_FILTER,e.NEAREST)}getStringValueHandler(){return`const uploadValue_${this.name} = ${this.varName};\n`}getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D_ARRAY,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!0),t.texImage3D(t.TEXTURE_2D_ARRAY,0,t.RGBA,e[0].width,e[0].height,e.length,0,t.RGBA,t.UNSIGNED_BYTE,null);for(let r=0;r{const{utils:r}=i(),{WebGL2KernelValueHTMLImageArray:s}=Le();t.exports={WebGL2KernelValueDynamicHTMLImageArray:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2DArray ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){const{width:t,height:r}=e[0];this.checkSize(t,r),this.dimensions=[t,r,e.length],this.textureSize=[t,r],this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Fe=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueHTMLImage:s}=ke();t.exports={WebGL2KernelValueHTMLVideo:class extends s{}}}),$e=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueDynamicHTMLImage:s}=Ce();t.exports={WebGL2KernelValueDynamicHTMLVideo:class extends s{}}}),Re=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleInput:s}=J();t.exports={WebGL2KernelValueSingleInput:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){const{context:t}=this;r.flattenTo(e.value,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Ne=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleInput:s}=Re();t.exports={WebGL2KernelValueDynamicSingleInput:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){let[t,s,n]=e.size;this.dimensions=new Int32Array([t||1,s||1,n||1]),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Me=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedInput:s}=ee();t.exports={WebGL2KernelValueUnsignedInput:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),Oe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicUnsignedInput:s}=te();t.exports={WebGL2KernelValueDynamicUnsignedInput:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),Ge=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueMemoryOptimizedNumberTexture:s}=re();t.exports={WebGL2KernelValueMemoryOptimizedNumberTexture:class extends s{getSource(){const{id:e,sizeId:t,textureSize:s,dimensionsId:n,dimensions:i}=this,a=this.getVariablePrecisionString();return r.linesToString([`uniform sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${s[0]}, ${s[1]})`,`${a} ivec3 ${n} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Ve=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicMemoryOptimizedNumberTexture:s}=se();t.exports={WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:class extends s{getSource(){return r.linesToString([`uniform sampler2D ${this.id}`,`uniform ivec2 ${this.sizeId}`,`uniform ivec3 ${this.dimensionsId}`])}}}}),Pe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueNumberTexture:s}=ne();t.exports={WebGL2KernelValueNumberTexture:class extends s{getSource(){const{id:e,sizeId:t,textureSize:s,dimensionsId:n,dimensions:i}=this,a=this.getVariablePrecisionString();return r.linesToString([`uniform ${a} sampler2D ${e}`,`${a} ivec2 ${t} = ivec2(${s[0]}, ${s[1]})`,`${a} ivec3 ${n} = ivec3(${i[0]}, ${i[1]}, ${i[2]})`])}}}}),Be=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicNumberTexture:s}=ie();t.exports={WebGL2KernelValueDynamicNumberTexture:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),ze=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray:s}=ae();t.exports={WebGL2KernelValueSingleArray:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}updateValue(e){if(!r.isArray(e))return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),Ue=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray:s}=ze();t.exports={WebGL2KernelValueDynamicSingleArray:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.dimensions=r.getDimensions(e,!0),this.textureSize=r.getMemoryOptimizedFloatTextureSize(this.dimensions,this.bitRatio),this.uploadArrayLength=this.textureSize[0]*this.textureSize[1]*this.bitRatio,this.checkSize(this.textureSize[0],this.textureSize[1]),this.uploadValue=new Float32Array(this.uploadArrayLength),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ke=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray1DI:s}=ue();t.exports={WebGL2KernelValueSingleArray1DI:class extends s{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),We=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray1DI:s}=Ke();t.exports={WebGL2KernelValueDynamicSingleArray1DI:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),je=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray2DI:s}=he();t.exports={WebGL2KernelValueSingleArray2DI:class extends s{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),qe=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray2DI:s}=je();t.exports={WebGL2KernelValueDynamicSingleArray2DI:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Xe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueSingleArray3DI:s}=pe();t.exports={WebGL2KernelValueSingleArray3DI:class extends s{updateValue(e){if(e.constructor!==this.initialValueConstructor)return void this.onUpdateValueMismatch(e.constructor);const{context:t}=this;r.flattenTo(e,this.uploadValue),t.activeTexture(this.contextHandle),t.bindTexture(t.TEXTURE_2D,this.texture),t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,!1),t.texImage2D(t.TEXTURE_2D,0,t.RGBA32F,this.textureSize[0],this.textureSize[1],0,t.RGBA,t.FLOAT,this.uploadValue),this.kernel.setUniform1i(this.id,this.index)}}}}),He=e((e,t)=>{const{utils:r}=i(),{WebGL2KernelValueSingleArray3DI:s}=Xe();t.exports={WebGL2KernelValueDynamicSingleArray3DI:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}updateValue(e){this.setShape(e),this.kernel.setUniform3iv(this.dimensionsId,this.dimensions),this.kernel.setUniform2iv(this.sizeId,this.textureSize),super.updateValue(e)}}}}),Ye=e((e,t)=>{const{WebGLKernelValueArray2:r}=fe();t.exports={WebGL2KernelValueArray2:class extends r{}}}),Ze=e((e,t)=>{const{WebGLKernelValueArray3:r}=me();t.exports={WebGL2KernelValueArray3:class extends r{}}}),Je=e((e,t)=>{const{WebGLKernelValueArray4:r}=ge();t.exports={WebGL2KernelValueArray4:class extends r{}}}),Qe=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueUnsignedArray:s}=ye();t.exports={WebGL2KernelValueUnsignedArray:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`${e} ivec2 ${this.sizeId} = ivec2(${this.textureSize[0]}, ${this.textureSize[1]})`,`${e} ivec3 ${this.dimensionsId} = ivec3(${this.dimensions[0]}, ${this.dimensions[1]}, ${this.dimensions[2]})`])}}}}),et=e((e,t)=>{const{utils:r}=i(),{WebGLKernelValueDynamicUnsignedArray:s}=xe();t.exports={WebGL2KernelValueDynamicUnsignedArray:class extends s{getSource(){const e=this.getVariablePrecisionString();return r.linesToString([`uniform ${e} sampler2D ${this.id}`,`uniform ${e} ivec2 ${this.sizeId}`,`uniform ${e} ivec3 ${this.dimensionsId}`])}}}}),tt=e((e,t)=>{const{WebGL2KernelValueBoolean:r}=_e(),{WebGL2KernelValueFloat:s}=Ee(),{WebGL2KernelValueInteger:n}=Ie(),{WebGL2KernelValueHTMLImage:i}=ke(),{WebGL2KernelValueDynamicHTMLImage:a}=Ce(),{WebGL2KernelValueHTMLImageArray:o}=Le(),{WebGL2KernelValueDynamicHTMLImageArray:u}=De(),{WebGL2KernelValueHTMLVideo:l}=Fe(),{WebGL2KernelValueDynamicHTMLVideo:h}=$e(),{WebGL2KernelValueSingleInput:c}=Re(),{WebGL2KernelValueDynamicSingleInput:p}=Ne(),{WebGL2KernelValueUnsignedInput:d}=Me(),{WebGL2KernelValueDynamicUnsignedInput:f}=Oe(),{WebGL2KernelValueMemoryOptimizedNumberTexture:m}=Ge(),{WebGL2KernelValueDynamicMemoryOptimizedNumberTexture:g}=Ve(),{WebGL2KernelValueNumberTexture:y}=Pe(),{WebGL2KernelValueDynamicNumberTexture:x}=Be(),{WebGL2KernelValueSingleArray:b}=ze(),{WebGL2KernelValueDynamicSingleArray:v}=Ue(),{WebGL2KernelValueSingleArray1DI:S}=Ke(),{WebGL2KernelValueDynamicSingleArray1DI:T}=We(),{WebGL2KernelValueSingleArray2DI:A}=je(),{WebGL2KernelValueDynamicSingleArray2DI:w}=qe(),{WebGL2KernelValueSingleArray3DI:_}=Xe(),{WebGL2KernelValueDynamicSingleArray3DI:E}=He(),{WebGL2KernelValueArray2:I}=Ye(),{WebGL2KernelValueArray3:k}=Ze(),{WebGL2KernelValueArray4:C}=Je(),{WebGL2KernelValueUnsignedArray:L}=Qe(),{WebGL2KernelValueDynamicUnsignedArray:D}=et(),F={unsigned:{dynamic:{Boolean:r,Integer:n,Float:s,Array:D,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:f,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:r,Float:s,Integer:n,Array:L,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":!1,"Array1D(3)":!1,"Array1D(4)":!1,"Array2D(2)":!1,"Array2D(3)":!1,"Array2D(4)":!1,"Array3D(2)":!1,"Array3D(3)":!1,"Array3D(4)":!1,Input:d,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:g,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}},single:{dynamic:{Boolean:r,Integer:n,Float:s,Array:v,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":T,"Array1D(3)":T,"Array1D(4)":T,"Array2D(2)":w,"Array2D(3)":w,"Array2D(4)":w,"Array3D(2)":E,"Array3D(3)":E,"Array3D(4)":E,Input:p,NumberTexture:x,"ArrayTexture(1)":x,"ArrayTexture(2)":x,"ArrayTexture(3)":x,"ArrayTexture(4)":x,MemoryOptimizedNumberTexture:g,HTMLCanvas:a,OffscreenCanvas:a,HTMLImage:a,ImageBitmap:a,ImageData:a,HTMLImageArray:u,HTMLVideo:h},static:{Boolean:r,Float:s,Integer:n,Array:b,"Array(2)":I,"Array(3)":k,"Array(4)":C,"Array1D(2)":S,"Array1D(3)":S,"Array1D(4)":S,"Array2D(2)":A,"Array2D(3)":A,"Array2D(4)":A,"Array3D(2)":_,"Array3D(3)":_,"Array3D(4)":_,Input:c,NumberTexture:y,"ArrayTexture(1)":y,"ArrayTexture(2)":y,"ArrayTexture(3)":y,"ArrayTexture(4)":y,MemoryOptimizedNumberTexture:m,HTMLCanvas:i,OffscreenCanvas:i,HTMLImage:i,ImageBitmap:i,ImageData:i,HTMLImageArray:o,HTMLVideo:l}}};t.exports={kernelValueMaps:F,lookupKernelValueType:function(e,t,r,s){if(!e)throw new Error("type missing");if(!t)throw new Error("dynamic missing");if(!r)throw new Error("precision missing");s.type&&(e=s.type);const n=F[r][t];if("WebGPUBuffer"===e)throw new Error("this kernel runs on WebGL but received a WebGPU pipeline buffer; await handle.toArray() first, or give this kernel the async contract (asyncMode: true / mode: 'async') so the readback happens for you");if(!1===n[e])return null;if(void 0===n[e])throw new Error(`Could not find a KernelValue for ${e}`);return n[e]}}}),rt=e((e,t)=>{const{WebGLKernel:r}=ve(),{WebGL2FunctionNode:s}=Te(),{FunctionBuilder:n}=u(),{utils:a}=i(),{fragmentShader:o}=Ae(),{vertexShader:l}=we(),{lookupKernelValueType:h}=tt();let c=null,p=null,d=null,f=null;t.exports={WebGL2Kernel:class extends r{static get isSupported(){return null!==c||(this.setupFeatureChecks(),c=this.isContextMatch(d)),c}static setupFeatureChecks(){"undefined"!=typeof document?p=document.createElement("canvas"):"undefined"!=typeof OffscreenCanvas&&(p=new OffscreenCanvas(0,0)),p&&(d=p.getContext("webgl2"),d&&d.getExtension&&(d.getExtension("EXT_color_buffer_float"),d.getExtension("OES_texture_float_linear"),f=this.getFeatures()))}static isContextMatch(e){return"undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext}static getFeatures(){const e=this.testContext;return Object.freeze({isFloatRead:this.getIsFloatRead(),isIntegerDivisionAccurate:this.getIsIntegerDivisionAccurate(),isSpeedTacticSupported:this.getIsSpeedTacticSupported(),kernelMap:!0,isTextureFloat:!0,isDrawBuffers:!0,channelCount:this.getChannelCount(),maxTextureSize:this.getMaxTextureSize(),lowIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT),lowFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT),mediumIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT),mediumFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT),highIntPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT),highFloatPrecision:e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT)})}static getIsTextureFloat(){return!0}static getChannelCount(){return d.getParameter(d.MAX_DRAW_BUFFERS)}static getMaxTextureSize(){return d.getParameter(d.MAX_TEXTURE_SIZE)}static lookupKernelValueType(e,t,r,s){return h(e,t,r,s)}static get testCanvas(){return p}static get testContext(){return d}static get features(){return f}static get fragmentShader(){return o}static get vertexShader(){return l}initContext(){return this.canvas.getContext("webgl2",{alpha:!1,depth:!1,antialias:!1})}initExtensions(){this.extensions={EXT_color_buffer_float:this.context.getExtension("EXT_color_buffer_float"),OES_texture_float_linear:this.context.getExtension("OES_texture_float_linear")}}validateSettings(e){if(!this.validate)return void(this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output));const{features:t}=this.constructor;if("single"===this.precision&&!t.isFloatRead)throw new Error("Float texture outputs are not supported");if(this.graphical||null!==this.precision||(this.precision=t.isFloatRead?"single":"unsigned"),null===this.fixIntegerDivisionAccuracy?this.fixIntegerDivisionAccuracy=!t.isIntegerDivisionAccurate:this.fixIntegerDivisionAccuracy&&t.isIntegerDivisionAccurate&&(this.fixIntegerDivisionAccuracy=!1),this.checkOutput(),!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=a.getVariableType(e[0],this.strictIntegers);switch(t){case"Array":this.output=a.getDimensions(t);break;case"NumberTexture":case"MemoryOptimizedNumberTexture":case"ArrayTexture(1)":case"ArrayTexture(2)":case"ArrayTexture(3)":case"ArrayTexture(4)":this.output=e[0].output;break;default:throw new Error("Auto output not supported for input type: "+t)}}if(this.graphical){if(2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");return"single"===this.precision&&(console.warn("Cannot use graphical mode and single precision at the same time"),this.precision="unsigned"),void(this.texSize=a.clone(this.output))}!this.graphical&&null===this.precision&&t.isTextureFloat&&(this.precision="single"),this.texSize=a.getKernelTextureSize({optimizeFloatMemory:this.optimizeFloatMemory,precision:this.precision},this.output),this.checkTextureSize()}translateSource(){const e=n.fromKernel(this,s,{fixIntegerDivisionAccuracy:this.fixIntegerDivisionAccuracy});this.translatedSource=e.getPrototypeString("kernel"),this.setupReturnTypes(e)}drawBuffers(){this.context.drawBuffers(this.drawBuffersMap)}getTextureFormat(){const{context:e}=this;switch(this.getInternalFormat()){case e.R32F:return e.RED;case e.RG32F:return e.RG;case e.RGBA32F:case e.RGBA:return e.RGBA;default:throw new Error("Unknown internal format")}}renderValues(){return void 0===this._tightRead&&this._detectTightRead(),super.renderValues()}renderKernelsToArrays(){return void 0===this._tightRead&&this._detectTightRead(),super.renderKernelsToArrays()}readFloatPixelsToFloat32Array(){if(!this._tightRead)return super.readFloatPixelsToFloat32Array();const{texSize:e,context:t}=this,r=e[0],s=e[1],n=new Float32Array(r*s);return t.readPixels(0,0,r,s,t.RED,t.FLOAT,n),n}renderOutputAsync(){return this.renderOutput!==this.renderValues?Promise.resolve(this.renderOutput()):this.renderValuesAsync()}renderValuesAsync(){void 0===this._tightRead&&this._detectTightRead();const e=this.formatValues,[t,r,s]=this.output;return this.transferValuesAsync().then(n=>e(n,t,r,s))}transferValuesAsync(){const{texSize:e,context:t}=this,r=e[0],s=e[1];let n,i,a;"single"===this.precision?(n=this._tightRead?t.RED:t.RGBA,i=t.FLOAT,a=new Float32Array(r*s*(this._tightRead?1:4))):(n=t.RGBA,i=t.UNSIGNED_BYTE,a=new Uint8Array(r*s*4));const o=t.createBuffer();t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.bufferData(t.PIXEL_PACK_BUFFER,a.byteLength,t.STREAM_READ),t.readPixels(0,0,r,s,n,i,0),t.bindBuffer(t.PIXEL_PACK_BUFFER,null);const u=t.fenceSync(t.SYNC_GPU_COMMANDS_COMPLETE,0);return t.flush(),this._pollFence(u).then(()=>(t.bindBuffer(t.PIXEL_PACK_BUFFER,o),t.getBufferSubData(t.PIXEL_PACK_BUFFER,0,a),t.bindBuffer(t.PIXEL_PACK_BUFFER,null),t.deleteBuffer(o),"single"===this.precision?a:new Float32Array(a.buffer)),e=>{throw t.deleteBuffer(o),e})}_pollFence(e){const t=this.context;return new Promise((r,s)=>{let n,i=null;"undefined"!=typeof MessageChannel?(i=new MessageChannel,i.port1.onmessage=()=>o(),n=()=>i.port2.postMessage(0)):n=()=>setTimeout(o,0);const a=(r,s)=>{t.deleteSync(e),i&&(i.port1.close(),i.port2.close()),r(s)},o=()=>{if(t.isContextLost())return a(s,new Error("WebGL context lost while awaiting kernel result"));const i=t.clientWaitSync(e,0,0);return i===t.ALREADY_SIGNALED||i===t.CONDITION_SATISFIED?a(r):i===t.WAIT_FAILED?a(s,new Error("clientWaitSync failed while awaiting kernel result")):void n()};o()})}_detectTightRead(){const e=this.context;this._tightRead=!1,e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t="Number"===this.returnType||"Float"===this.returnType||"Integer"===this.returnType||"LiteralInteger"===this.returnType;if("single"===this.precision&&!this.optimizeFloatMemory&&!this.graphical&&t&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_FORMAT)===e.RED&&e.getParameter(e.IMPLEMENTATION_COLOR_READ_TYPE)===e.FLOAT){if(this.formatValues===a.erectFloat)this.formatValues=a.erectMemoryOptimizedFloat;else if(this.formatValues===a.erect2DFloat)this.formatValues=a.erectMemoryOptimized2DFloat;else if(this.formatValues===a.erect3DFloat)this.formatValues=a.erectMemoryOptimized3DFloat;else if(this.formatValues!==a.erectMemoryOptimizedFloat&&this.formatValues!==a.erectMemoryOptimized2DFloat&&this.formatValues!==a.erectMemoryOptimized3DFloat)return;this._tightRead=!0}}getInternalFormat(){const{context:e}=this;if("single"===this.precision)switch(this.returnType){case"Number":case"Float":case"Integer":return this.optimizeFloatMemory?e.RGBA32F:e.R32F;case"Array(2)":return e.RG32F;case"Array(3)":case"Array(4)":return e.RGBA32F;default:throw new Error("Unhandled return type")}return e.RGBA}_setupOutputTexture(){const e=this.context;if(this.texture)return e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.texture.texture,0),void(this._tightRead=void 0);e.bindFramebuffer(e.FRAMEBUFFER,this.framebuffer);const t=e.createTexture(),r=this.texSize;e.activeTexture(e.TEXTURE0+this.constantTextureCount+this.argumentTextureCount),e.bindTexture(e.TEXTURE_2D,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.REPEAT),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST);const s=this.getInternalFormat();"single"===this.precision?e.texStorage2D(e.TEXTURE_2D,1,s,r[0],r[1]):e.texImage2D(e.TEXTURE_2D,0,s,r[0],r[1],0,s,e.UNSIGNED_BYTE,null),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0),this.texture=new this.TextureConstructor({texture:t,size:r,dimensions:this.threadDim,output:this.output,context:this.context,internalFormat:this.getInternalFormat(),textureFormat:this.getTextureFormat(),kernel:this}),this._tightRead=void 0}_setupSubOutputTextures(){const e=this.context;if(this.mappedTextures){for(let t=0;t{const{utils:r}=i(),{FunctionNode:s}=h();const n={Number:"f32",Float:"f32",Integer:"i32",LiteralInteger:"f32",Boolean:"bool","Array(2)":"vec2","Array(3)":"vec3","Array(4)":"vec4"},a={"===":"==","!==":"!="},o=["x","y","z","w"],u={pow:"_pow",round:"_round"},l={ceil:!0,floor:!0,_round:!0};t.exports={WGSLFunctionNode:class extends s{get requiresSequenceFreeForInit(){return!0}wgslFloat(e){if(e===1/0)return"0x1.fffffep+127";if(e===-1/0)return"-0x1.fffffep+127";if(e>34028234663852886e22)return"0x1.fffffep+127";if(e<-34028234663852886e22)return"-0x1.fffffep+127";const t=`${e}`;return-1!==t.indexOf(".")||-1!==t.indexOf("e")||-1!==t.indexOf("E")?t:`${t}.0`}wgslInt(e){return`${Math.round(e)}`}mangleFunctionName(e){return`fn_${r.sanitizeName(e)}`}getLookupType(e){return"WebGPUBuffer"===e?"Number":super.getLookupType(e)}astUpdateExpression(e,t){return this.astGeneric(e.argument,t),t.push(e.operator),t}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}astConditionalExpression(e,t){if("ConditionalExpression"!==e.type)throw this.astErrorOutput("Not a conditional expression",e);const r=this.getType(e.consequent),s=this.getType(e.alternate);if(null===r&&null===s)return t.push("if ("),this.astGeneric(e.test,t),t.push(") {"),this.astGeneric(e.consequent,t),t.push(";"),t.push("} else {"),this.astGeneric(e.alternate,t),t.push(";"),t.push("}"),t;let n="LiteralInteger"===r?"Number":r;"Integer"!==n||"Number"!==s&&"Float"!==s||(n="Number");const i=e=>{const r=this.getType(e);switch(n){case"Number":case"Float":"Integer"===r?this.castValueToFloat(e,t):"LiteralInteger"===r?this.castLiteralToFloat(e,t):this.astGeneric(e,t);break;case"Integer":"Number"===r||"Float"===r?this.castValueToInteger(e,t):"LiteralInteger"===r?this.castLiteralToInteger(e,t):this.astGeneric(e,t);break;default:this.astGeneric(e,t)}};return t.push("select("),i(e.alternate),t.push(", "),i(e.consequent),t.push(", "),this.astGeneric(e.test,t),t.push(")"),t}astFunction(e,t){if(this.isRootKernel){for(let r=0;r0&&t.push(", ");let a=this.argumentTypes[this.argumentNames.indexOf(i)];if(!a)throw this.astErrorOutput(`Unknown argument ${i} type`,e);"LiteralInteger"===a&&(this.argumentTypes[s]=a="Number");const o=n[a];if(!o)throw this.astErrorOutput(`WebGPU backend does not yet support ${a} arguments to helper functions`,e);t.push(`user_${r.sanitizeName(i)} : ${o}`)}t.push(")"),i&&t.push(` -> ${i}`),t.push(" {\n");for(let r=0;r>":!0,">>>":!0}[e.operator])return null;const r=e=>{switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;default:this.pushState("building-integer"),this.astGeneric(e,t),this.popState("building-integer")}};return t.push("("),">>>"===e.operator?(t.push("bitcast(bitcast("),r(e.left),t.push(") >> u32("),r(e.right),t.push("))")):"<<"===e.operator||">>"===e.operator?(r(e.left),t.push(` ${e.operator} u32(`),r(e.right),t.push(")")):(r(e.left),t.push(` ${e.operator} `),r(e.right)),t.push(")"),t}checkAndUpconvertBitwiseUnary(e,t){if("~"!==e.operator)return null;switch(t.push("~("),this.getType(e.argument)){case"Number":case"Float":this.castValueToInteger(e.argument,t);break;case"LiteralInteger":this.castLiteralToInteger(e.argument,t);break;default:this.astGeneric(e.argument,t)}return t.push(")"),t}astUnaryExpression(e,t){return this.checkAndUpconvertBitwiseUnary(e,t)?t:"+"===e.operator?(this.astGeneric(e.argument,t),t):(e.prefix?(t.push(e.operator),this.astGeneric(e.argument,t)):(this.astGeneric(e.argument,t),t.push(e.operator)),t)}castLiteralToInteger(e,t){return this.pushState("casting-to-integer"),this.astGeneric(e,t),this.popState("casting-to-integer"),t}castLiteralToFloat(e,t){return this.pushState("casting-to-float"),this.astGeneric(e,t),this.popState("casting-to-float"),t}castValueToInteger(e,t){return this.pushState("casting-to-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-integer"),t}castValueToFloat(e,t){return this.pushState("casting-to-float"),t.push("f32("),this.astGeneric(e,t),t.push(")"),this.popState("casting-to-float"),t}astIdentifierExpression(e,t){if("Identifier"!==e.type)throw this.astErrorOutput("IdentifierExpression - not an Identifier",e);const s=this.getType(e),n=r.sanitizeName(e.name);return"Infinity"===e.name?(t.push("0x1.fffffep+127"),t):!this.isRootKernel||-1===this.argumentNames.indexOf(e.name)||"Number"!==s&&"Float"!==s&&"Integer"!==s&&"Boolean"!==s?(t.push(`user_${n}`),t):("Boolean"===s?t.push(`bool(params.user_${n})`):t.push(`params.user_${n}`),t)}astForStatement(e,t){if("ForStatement"!==e.type)throw this.astErrorOutput("Invalid for statement",e);const r=[],s=[],n=[],i=[];let a=null;if(e.init){const{declarations:t}=e.init;t.length>1&&(a=!1),this.astGeneric(e.init,r);for(let e=0;e0&&t.push(r.join(""),"\n"),t.push(`for (var ${e} : i32 = 0;${e}0&&t.push(`if (!(${s.join("")})) { break; }\n`),t.push(i.join("")),t.push(`\n${n.join("")};`),t.push("}\n")}return t}astWhileStatement(e,t){if("WhileStatement"!==e.type)throw this.astErrorOutput("Invalid while statement",e);const r=this.getInternalVariableName("safeI");return t.push(`for (var ${r} : i32 = 0;${r}{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(t);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const r in e)if("loc"!==r&&"range"!==r&&"parent"!==r&&t(e[r]))return!0;return!1};if(t(r[e]))throw this.astErrorOutput("break inside a switch case is only supported as the case terminator",r[e])}for(let e=0;ee+1){l=!0,this.astSwitchCaseConsequent(s[e].consequent,u);continue}t.push(" else {\n")}this.astSwitchCaseConsequent(s[e].consequent,t),t.push("\n}")}return l&&(t.push(" else {"),t.push(u.join("")),t.push("}")),t.push("\n"),t}astThisExpression(e,t){return t.push("this"),t}astSequenceExpression(e,t){const{expressions:r}=e;if(1===r.length)return this.astGeneric(r[0],t),t;throw this.astErrorOutput("WebGPU backend does not yet support the comma operator",e)}astMemberExpression(e,t){const{property:s,name:i,signature:a,origin:o,type:u,xProperty:l,yProperty:h,zProperty:c}=this.getMemberExpressionDetails(e);switch(a){case"value.thread.value":case"this.thread.value":if("x"!==i&&"y"!==i&&"z"!==i)throw this.astErrorOutput("Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`",e);return t.push(`i32(threadGid.${i})`),t;case"this.output.value":{const r={x:0,y:1,z:2}[i];if(void 0===r)throw this.astErrorOutput("Unexpected expression",e);if(this.dynamicOutput){const e=`params.output${i.toUpperCase()}`;this.isState("casting-to-float")?t.push(`f32(${e})`):t.push(`i32(${e})`)}else this.isState("casting-to-integer")?t.push(`${this.output[r]}`):t.push(`${this.output[r]}.0`);return t}case"value":throw this.astErrorOutput("Unexpected expression",e);case"value[]":case"value[][]":case"value[][][]":case"value[][][][]":case"value.value":if("Math"===o)return t.push(this.wgslFloat(Math[i])),t;switch(s){case"r":return t.push(`user_${r.sanitizeName(i)}.x`),t;case"g":return t.push(`user_${r.sanitizeName(i)}.y`),t;case"b":return t.push(`user_${r.sanitizeName(i)}.z`),t;case"a":return t.push(`user_${r.sanitizeName(i)}.w`),t}break;case"this.constants.value":{const r=this.constants[i];switch(u){case"Integer":return this.isState("casting-to-float")?t.push(this.wgslFloat(r)):t.push(this.wgslInt(r)),t;case"Number":case"Float":return this.isState("casting-to-integer")?t.push(this.wgslInt(r)):t.push(this.wgslFloat(r)),t;case"Boolean":return t.push(r?"true":"false"),t;case"Array(2)":case"Array(3)":case"Array(4)":{const e=parseInt(u.substring(6),10),s=[];for(let t=0;t4)throw this.astErrorOutput("this.color takes (r, g, b) or (r, g, b, a)",e);t.push("kernelColor(data_index");for(let r=0;r0&&t.push(", "),n){case"Integer":this.castValueToFloat(s,t);break;case"LiteralInteger":this.castLiteralToFloat(s,t);break;default:this.astGeneric(s,t)}}else{const n=this.lookupFunctionArgumentTypes(s)||[];for(let i=0;i0&&t.push(", ");const u=this.getType(a);switch(o||(this.triggerImplyArgumentType(s,i,u,this),o=u),u){case"Boolean":this.astGeneric(a,t);continue;case"Number":case"Float":if("Integer"===o){t.push("i32("),this.astGeneric(a,t),t.push(")");continue}if("Number"===o||"Float"===o){this.astGeneric(a,t);continue}if("LiteralInteger"===o){this.castLiteralToFloat(a,t);continue}break;case"Integer":if("Number"===o||"Float"===o){t.push("f32("),this.astGeneric(a,t),t.push(")");continue}if("Integer"===o){this.pushState("building-integer"),this.astGeneric(a,t),this.popState("building-integer");continue}break;case"LiteralInteger":if("Integer"===o){this.castLiteralToInteger(a,t);continue}if("Number"===o||"Float"===o){this.castLiteralToFloat(a,t);continue}if("LiteralInteger"===o){this.astGeneric(a,t);continue}break;case"Array(2)":case"Array(3)":case"Array(4)":if(o===u){"Identifier"===a.type?t.push(`user_${r.sanitizeName(a.name)}`):this.astGeneric(a,t);continue}break;case"Array":case"Array2D":case"Array3D":case"Input":case"WebGPUBuffer":throw this.astErrorOutput("WebGPU backend does not yet support array arguments to helper functions",e)}throw this.astErrorOutput(`Unhandled argument combination of ${u} and ${o} for argument named "${a.name}"`,e)}}return t.push(")"),a&&t.push(")"),t}astArrayExpression(e,t){switch(this.getType(e)){case"Matrix(2)":case"Matrix(3)":case"Matrix(4)":throw this.astErrorOutput("WebGPU backend does not yet support Matrix types",e)}const r=e.elements.length;t.push(`vec${r}(`);for(let s=0;s0&&t.push(", ");const r=e.elements[s];switch(this.getType(r)){case"Integer":this.castValueToFloat(r,t);break;case"LiteralInteger":this.castLiteralToFloat(r,t);break;default:this.astGeneric(r,t)}}return t.push(")"),t}memberExpressionXYZ(e,t,r,s){return r?s.push(this.memberExpressionPropertyMarkup(r),", "):s.push("0, "),t?s.push(this.memberExpressionPropertyMarkup(t),", "):s.push("0, "),s.push(this.memberExpressionPropertyMarkup(e)),s}memberExpressionPropertyMarkup(e){if(!e)throw new Error("Property not set");const t=[];switch(this.getType(e)){case"Number":case"Float":this.castValueToInteger(e,t);break;case"LiteralInteger":this.castLiteralToInteger(e,t);break;case"Integer":this.pushState("building-integer"),t.push("i32("),this.astGeneric(e,t),t.push(")"),this.popState("building-integer");break;default:this.astGeneric(e,t)}return t.join("")}}}}),nt=e((e,t)=>{let r=null;t.exports={WebGPUContext:class e{static get isSupported(){return"undefined"!=typeof navigator&&!!navigator.gpu}static acquire(){if(r)return r;const t=(async()=>{if(!e.isSupported)throw new Error("WebGPU is not supported on this platform (navigator.gpu is missing)");const s=await navigator.gpu.requestAdapter();if(!s)throw new Error("WebGPU is present (navigator.gpu) but no adapter is available. On headless Chromium there is no adapter; run headed. Use `await GPU.isWebGPUAvailable()` to feature-detect.");const n=await s.requestDevice({requiredLimits:{maxStorageBufferBindingSize:s.limits.maxStorageBufferBindingSize,maxBufferSize:s.limits.maxBufferSize}}),i={adapter:s,device:n,isLost:!1};return n.lost.then(e=>{i.isLost=!0,"destroyed"!==e.reason&&console.error(`gpu.js [webgpu]: device lost: ${e.message}`),r===t&&(r=null)}),n.onuncapturederror=e=>{console.error(`gpu.js [webgpu]: ${e.error.message}`)},i})();return t.catch(()=>{r===t&&(r=null)}),r=t}static destroy(){if(!r)return Promise.resolve();const e=r;return r=null,e.then(({device:e})=>{e.destroy()},()=>{})}}}}),it=e((e,t)=>{t.exports={WebGPUBufferResult:class e{constructor(e){this.buffer=e.buffer,this.output=e.output,this.componentCount=e.componentCount||1,this.context=e.context,this.kernel=e.kernel,this.type="WebGPUBuffer",this._deleted=!1,this.buffer._refs?this.buffer._refs++:this.buffer._refs=1}toArray(){return this._deleted?Promise.reject(new Error("WebGPUBufferResult has been deleted")):this.kernel.readBufferResult(this)}delete(){this._deleted||(this._deleted=!0,0===--this.buffer._refs&&this.buffer.destroy())}clone(){return new e(this)}}}}),at=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:n}=u(),{WGSLFunctionNode:o}=st(),{WebGPUContext:l}=nt(),{WebGPUBufferResult:h}=it(),{utils:c}=i(),{Input:p}=s(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0}),f={_pow:"fn _pow(v1 : f32, v2 : f32) -> f32 {\n if (v2 == 0.0) { return 1.0; }\n return pow(v1, v2);\n}",_round:"fn _round(x : f32) -> f32 {\n return floor(x + 0.5);\n}",cbrt:"fn cbrt(x : f32) -> f32 {\n return sign(x) * pow(abs(x), 1.0 / 3.0);\n}",expm1:"fn expm1(x : f32) -> f32 {\n return exp(x) - 1.0;\n}",fround:"fn fround(x : f32) -> f32 {\n return x;\n}",imul:"fn imul(a : f32, b : f32) -> f32 {\n return f32(i32(a) * i32(b));\n}",log10:`fn log10(x : f32) -> f32 {\n return log2(x) * ${1/Math.log2(10)};\n}`,log1p:"fn log1p(x : f32) -> f32 {\n return log(1.0 + x);\n}",clz32:"fn clz32(x : f32) -> f32 {\n return f32(countLeadingZeros(u32(x)));\n}"};t.exports={WebGPUKernel:class extends r{static get isSupported(){return l.isSupported}static get isAsync(){return!0}static isContextMatch(e){return Boolean(e&&"function"==typeof e.createShaderModule&&"function"==typeof e.createComputePipeline)}static getFeatures(){return d}static get features(){return d}static get mode(){return"webgpu"}static getSignature(e,t){return"webgpu"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static nativeFunctionArguments(){throw new Error("WebGPU backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebGPU backend does not yet support native functions")}static combineKernels(){throw new Error("WebGPU backend does not yet support combineKernels; chain kernels with `await` and pipeline mode instead")}constructor(e,t){if(super(e,t),t){if("unsigned"===t.precision&&!t.graphical)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(t.subKernels)throw new Error("WebGPU backend does not yet support createKernelMap")}this.mergeSettings(e.settings||t),(null===this.precision||this.graphical)&&(this.precision="single"),this.asyncMode=!0,this.threadDim=null,this.componentCount=1,this.compiledSource=null,this.translatedBody=null,this.translatedFunctions=null,this.paramsLayout=null,this._buildPromise=null,this._device=null,this.computePipeline=null,this.bindGroupLayout=null,this.bindGroup=null,this.bindGroupDirty=!0,this.paramsBuffer=null,this.paramsMirror=null,this.outputBuffer=null,this.argumentBuffers=null,this.constantBuffers=null,this.stagingPool=[],this._canvasContext=null,this._blitPipeline=null,this._blitParamsBuffer=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built){if(!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");if(t.length!==this.output.length)throw new Error("WebGPU backend does not yet support changing the output rank of a built kernel; the workgroup shape is fixed at build")}return this.output=t,this}toString(){throw new Error("WebGPU backend does not yet support toString")}validateSettings(e){if(this.graphical){if(!this.output||2!==this.output.length)throw new Error("Output must have 2 dimensions on graphical mode");if(this.pipeline)throw new Error("graphical mode and pipeline mode are mutually exclusive");if(!this.canvas)throw new Error("graphical mode requires a canvas (none could be created; pass one in settings)")}if("unsigned"===this.precision)throw new Error("WebGPU backend does not yet support precision: 'unsigned'; it is single precision only");if(this.precision="single",this.subKernels&&this.subKernels.length>0)throw new Error("WebGPU backend does not yet support createKernelMap");if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"===t)this.output=Array.from(c.getDimensions(e[0]));else{if("WebGPUBuffer"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(e[0].output)}}this.checkOutput()}setupArguments(e){super.setupArguments(e);for(let e=0;e{this.translateSource(),this.paramsLayout=this.computeParamsLayout(),this.compiledSource=this.assembleWGSL()}),this.debug&&(console.log("WGSL Shader Output:"),console.log(this.compiledSource)),this.buildSignature(arguments),this._buildPromise=this._buildAsync()}translateSource(){const e=n.fromKernel(this,o),t=e.getPrototypes("kernel");if(this.translatedBody=t[t.length-1],this.translatedFunctions=t.slice(0,-1).join("\n"),this.graphical)this.componentCount=4;else switch(this.returnType||(this.returnType=e.getKernelResultType()),this.returnType){case"Number":case"Float":case"Integer":case"LiteralInteger":this.componentCount=1;break;case"Array(2)":this.componentCount=2;break;case"Array(3)":this.componentCount=3;break;case"Array(4)":this.componentCount=4;break;default:throw new Error(`WebGPU backend does not yet support returning ${this.returnType}`)}}computeParamsLayout(){const e=[],t=[];let r=16;for(let s=0;s,`);for(let e=0;e params : Params;");for(let t=0;t user_${e[t].name} : array;`);const i=1+e.length;s.push(`@group(0) @binding(${i}) var result : array;`),this.graphical&&s.push("fn kernelColor(index : i32, r : f32, g : f32, b : f32, a : f32) {\n result[index * 4] = r;\n result[index * 4 + 1] = g;\n result[index * 4 + 2] = b;\n result[index * 4 + 3] = a;\n}");for(let e=0;e constants_${r[e].name} : array;`);s.push("var threadGid : vec3;"),null!==this.paramsLayout.randomSeedOffset&&s.push("var pcgState : u32;\nfn pcg_random() -> f32 {\n pcgState = pcgState * 747796405u + 2891336453u;\n let word = ((pcgState >> ((pcgState >> 28u) + 4u)) ^ pcgState) * 277803737u;\n let mixed = (word >> 22u) ^ word;\n return f32(mixed >> 8u) / 16777216.0;\n}");const a=`${this.translatedFunctions}\n${this.translatedBody}`;/\bLOOP_MAX\b/.test(a)&&s.push(`const LOOP_MAX : i32 = ${parseInt(this.loopMaxIterations,10)||1e3};`);for(const e in f)new RegExp(`\\b${e}\\(`).test(a)&&s.push(f[e]);for(let t=0;t f32 {\n return user_${r}[u32(x + i32(params.user_${r}_dims.x) * (y + i32(params.user_${r}_dims.y) * z))];\n}`)}for(let e=0;e f32 {\n return constants_${t.name}[u32(x + ${i[0]} * (y + ${i[1]} * z))];\n}`)}this.translatedFunctions&&s.push(this.translatedFunctions);const o=1===this.output.length?[64,1,1]:[8,8,1];return this.workgroupSize=o,1===this.output.length?s.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n let flat_index : u32 = gid.x + gid.y * params.dispatchWidth;\n threadGid = vec3(flat_index, 0u, 0u);\n if (flat_index >= params.outputX) { return; }\n let data_index : i32 = i32(flat_index);\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`):s.push(`@compute @workgroup_size(${o[0]}, ${o[1]}, ${o[2]})\nfn main(@builtin(global_invocation_id) gid : vec3) {\n threadGid = gid;\n if (gid.x >= params.outputX || gid.y >= params.outputY || gid.z >= params.outputZ) { return; }\n let data_index : i32 = i32(gid.x + params.outputX * (gid.y + params.outputY * gid.z));\n${null!==this.paramsLayout.randomSeedOffset?" pcgState = (params.randomSeed + u32(data_index) * 2654435769u) * 747796405u + 2891336453u;\n":""}${this.translatedBody}\n}`),s.join("\n")}constantDimensions(e){const t=e instanceof p?Array.from(e.size):Array.from(c.getDimensions(e));for(;t.length<3;)t.push(1);return t}async _buildAsync(){const e=await l.acquire();this.context=e;const t=this._device=e.device,r=t.createShaderModule({code:this.compiledSource}),s=(await r.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(s.length>0)throw new Error("Error compiling WGSL compute shader:\n"+s.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n")+`\n--- generated WGSL ---\n${this.compiledSource}`);const{arrayArgs:n,bufferConstants:i,byteLength:a}=this.paramsLayout,o=[{binding:0,visibility:4,buffer:{type:"uniform"}}];for(let e=0;ei&&(n[1]=Math.ceil(n[0]/i),n[0]=Math.ceil(n[0]/n[1])),a=n[0]*t);for(let e=0;e<3;e++)if(n[e]>i)throw new Error(`output dimension ${e} needs ${n[e]} workgroups, over this device's limit of ${i}`);return{groups:n,dispatchWidth:a}}async _buildBlitPipeline(e){if(this.canvas.width=this.output[0],this.canvas.height=this.output[1],this._canvasContext=this.canvas.getContext("webgpu"),!this._canvasContext)throw new Error("could not get a webgpu context from the canvas");const t=navigator.gpu.getPreferredCanvasFormat();this._canvasContext.configure({device:e,format:t,alphaMode:"premultiplied"});const r=e.createShaderModule({code:"struct BlitParams { width : u32, height : u32, pad0 : u32, pad1 : u32 }\n@group(0) @binding(0) var blit : BlitParams;\n@group(0) @binding(1) var pixels : array;\n@vertex fn vs(@builtin(vertex_index) vi : u32) -> @builtin(position) vec4 {\n var pos = array, 3>(vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));\n return vec4(pos[vi], 0.0, 1.0);\n}\n@fragment fn fs(@builtin(position) pos : vec4) -> @location(0) vec4 {\n let x = u32(pos.x);\n let y = u32(pos.y);\n let row = blit.height - 1u - y;\n let i = (row * blit.width + x) * 4u;\n let a = pixels[i + 3u];\n return vec4(pixels[i] * a, pixels[i + 1u] * a, pixels[i + 2u] * a, a);\n}"}),s=(await r.getCompilationInfo()).messages.filter(e=>"error"===e.type);if(s.length>0)throw new Error("Error compiling the graphical blit shader:\n"+s.map(e=>` ${e.lineNum}:${e.linePos} ${e.message}`).join("\n"));this._blitBindGroupLayout=e.createBindGroupLayout({entries:[{binding:0,visibility:2,buffer:{type:"uniform"}},{binding:1,visibility:2,buffer:{type:"read-only-storage"}}]}),this._blitPipeline=e.createRenderPipeline({layout:e.createPipelineLayout({bindGroupLayouts:[this._blitBindGroupLayout]}),vertex:{module:r,entryPoint:"vs"},fragment:{module:r,entryPoint:"fs",targets:[{format:t}]},primitive:{topology:"triangle-list"}}),this._blitParamsBuffer=e.createBuffer({size:16,usage:72})}_ensureOutputBuffer(){const[e,t,r]=this.threadDim,s=e*t*r*4*this.componentCount;this.immutable&&this.pipeline&&this.outputBuffer&&(0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this.outputBuffer=null,this.bindGroupDirty=!0),this.outputBuffer&&this.outputBuffer.size>=s||(this.outputBuffer&&0===--this.outputBuffer._refs&&this.outputBuffer.destroy(),this._checkBufferSize(s,`output [${this.output.join(", ")}]`),this.outputBuffer=this._device.createBuffer({size:s,usage:132}),this.outputBuffer._refs=1,this.bindGroupDirty=!0)}_checkBufferSize(e,t){const r=this._device.limits,s=Math.min(r.maxStorageBufferBindingSize,r.maxBufferSize);if(e>s)throw new Error(`WebGPU backend: ${t} needs ${e} bytes but this device allows ${s} per storage buffer (maxStorageBufferBindingSize/maxBufferSize); reduce the output or split the work across kernels`)}_snapshotArguments(e){const t=new Array(e.length);for(let r=0;rthis._runInternal(e))}_runInternal(e){if(this.context&&this.context.isLost)throw new Error("WebGPU device was lost; call kernel.destroy() (or gpu.destroy()) and run again to rebuild on a fresh device");const t=this._device,r=t.queue,{arrayArgs:s,scalarArgs:n,bufferConstants:i}=this.paramsLayout,a=this.threadDim=Array.from(this.output);for(;a.length<3;)a.push(1);if(this._ensureOutputBuffer(),null!==this.paramsLayout.randomSeedOffset){const e=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0;this.paramsU32[this.paramsLayout.randomSeedOffset/4]=e}this.paramsU32[0]=a[0],this.paramsU32[1]=a[1],this.paramsU32[2]=a[2],this.paramsU32[3]=this._computeDispatch(a).dispatchWidth;for(let n=0;n{const e=new Float32Array(p.buffer.getMappedRange(0,u).slice(0));return p.buffer.unmap(),this._releaseStaging(p),this._shapeOutput(e,d,this.componentCount)},e=>{throw this._releaseStaging(p),e})}_acquireStaging(e){for(let t=0;t=e)return r.busy=!0,r}const t={buffer:this._device.createBuffer({size:e,usage:9}),size:e,busy:!0,pooled:this.stagingPool.length<3};return t.pooled&&this.stagingPool.push(t),t}_releaseStaging(e){e.pooled?e.busy=!1:e.buffer.destroy()}_shapeOutput(e,t,r){const[s,n,i]=[t[0],t[1]||1,t[2]||1];if(1===r)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,s);case 2:return c.erectMemoryOptimized2DFloat(e,s,n);default:return c.erectMemoryOptimized3DFloat(e,s,n,i)}const a=r,o=t=>{const r=new Array(s);for(let n=0;n{const t=new Float32Array(i.buffer.getMappedRange(0,n).slice(0));return i.buffer.unmap(),this._releaseStaging(i),this._shapeOutput(t,r,e.componentCount)},e=>{throw this._releaseStaging(i),e})}getPixels(e){if(!this.graphical)return Promise.reject(new Error("getPixels only works on a graphical kernel"));if(!this.outputBuffer)return Promise.reject(new Error("run the kernel before reading its pixels"));const[t,r]=this.output,s=t*r*4*4,n=this._acquireStaging(s),i=this._device.createCommandEncoder();return i.copyBufferToBuffer(this.outputBuffer,0,n.buffer,0,s),this._device.queue.submit([i.finish()]),n.buffer.mapAsync(1,0,s).then(()=>{const i=new Float32Array(n.buffer.getMappedRange(0,s).slice(0));n.buffer.unmap(),this._releaseStaging(n);const a=new Uint8ClampedArray(t*r*4);for(let s=0;s{throw this._releaseStaging(n),e})}destroy(e){if(this._blitParamsBuffer&&(this._blitParamsBuffer.destroy(),this._blitParamsBuffer=null),this._canvasContext&&(this._canvasContext.unconfigure(),this._canvasContext=null),this._blitPipeline=null,this._blitBindGroup=null,this._blitBoundOutputBuffer=null,this.paramsBuffer&&(this.paramsBuffer.destroy(),this.paramsBuffer=null),this.paramsLayout)for(let e=0;e{const r={i32:127,i64:126,f32:125,f64:124,v128:123},s=new DataView(new ArrayBuffer(16));function n(e,t){let r=e>>>0;do{let e=127&r;r>>>=7,0!==r&&(e|=128),t.push(e)}while(0!==r)}function i(e,t){let r=0|e;for(;;){const e=127&r;if(r>>=7,0===r&&!(64&e)||-1===r&&64&e)return void t.push(e);t.push(128|e)}}function a(e,t,r){let s=e>>>0;for(let e=0;e<4;e++)t[r+e]=127&s|128,s>>>=7;t[r+4]=127&s}function o(e,t){const r=[];for(let t=0;t65535&&t++,s<128?r.push(s):s<2048?r.push(192|s>>6,128|63&s):s<65536?r.push(224|s>>12,128|s>>6&63,128|63&s):r.push(240|s>>18,128|s>>12&63,128|s>>6&63,128|63&s)}n(r.length,t);for(let e=0;e3)throw new Error(`WasmModuleBuilder: lane index ${t} out of range for 4-lane shape`);return this.bytes.push(253,e,t),this}_push(e){for(let t=0;t${t.join(",")}`;if(r in this.typeIndexByKey)return this.typeIndexByKey[r];const s=this.types.length;return this.types.push({params:e,results:t}),this.typeIndexByKey[r]=s,s}addMemoryImport(e,t,r=!1){if(r&&null==t)throw new Error("WasmModuleBuilder: shared memory import requires a maximum");return this.memoryImport={initial:e,maximum:t,shared:r},this}addFuncImport(e,t,r,s="env"){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);const n=this.funcImports.length;return this.funcImports.push({name:e,module:s,typeIndex:this._typeIndex(t,r)}),this.funcImportIndexByName[e]=n,n}addGlobal(e,t,r){return u(e),this.globals.push({type:e,mutable:t,initialValue:r}),this.globals.length-1}addFunction(e,{params:t=[],results:r=[],locals:s=[]}={}){if(e in this.funcImportIndexByName||e in this.functionIndexByName)throw new Error(`WasmModuleBuilder: duplicate function name "${e}"`);t.forEach(u),r.forEach(u),s.forEach(u);const n=new h(this,e,t,r,s);return this.functionIndexByName[e]=this.functions.length,this.functions.push({name:e,emitter:n,typeIndex:this._typeIndex(t,r)}),n}exportFunction(e,t=e){return this.exports.push({name:e,exportName:t}),this}_resolveFuncIndex(e){if(e in this.funcImportIndexByName)return this.funcImportIndexByName[e];if(e in this.functionIndexByName)return this.funcImports.length+this.functionIndexByName[e];throw new Error(`WasmModuleBuilder: call target "${e}" is not an import or a defined function`)}_section(e,t,r){r.push(e),n(t.length,r);for(let e=0;e0){const t=[];n(this.types.length,t);for(const{params:e,results:r}of this.types){t.push(96),n(e.length,t);for(const r of e)t.push(u(r));n(r.length,t);for(const e of r)t.push(u(e))}this._section(1,t,e)}if(null!==this.memoryImport||this.funcImports.length>0){const t=[];if(n((null!==this.memoryImport?1:0)+this.funcImports.length,t),null!==this.memoryImport){const{initial:e,maximum:r,shared:s}=this.memoryImport;o("env",t),o("memory",t),t.push(2);const i=null!=r;t.push(s?3:i?1:0),n(e,t),i&&n(r,t)}for(const{name:e,module:r,typeIndex:s}of this.funcImports)o(r,t),o(e,t),t.push(0),n(s,t);this._section(2,t,e)}if(this.functions.length>0){const t=[];n(this.functions.length,t);for(const{typeIndex:e}of this.functions)n(e,t);this._section(3,t,e)}if(this.globals.length>0){const t=[];n(this.globals.length,t);for(const{type:e,mutable:r,initialValue:n}of this.globals){if(t.push(u(e),r?1:0),"i32"===e)t.push(65),i(n,t);else if("f32"===e){t.push(67),s.setFloat32(0,n,!0);for(let e=0;e<4;e++)t.push(s.getUint8(e))}else{if("v128"!==e)throw new Error(`WasmModuleBuilder: no initializer encoding for global type "${e}"`);t.push(253,12);for(let e=0;e<16;e++)t.push(0)}t.push(11)}this._section(6,t,e)}if(this.exports.length>0){const t=[];n(this.exports.length,t);for(const{name:e,exportName:r}of this.exports)o(r,t),t.push(0),n(this._resolveFuncIndex(e),t);this._section(7,t,e)}if(this.functions.length>0){const t=[];n(this.functions.length,t);for(const{emitter:e}of this.functions){const r=e.bytes.slice();for(const{at:t,name:s}of e.callFixups)a(this._resolveFuncIndex(s),r,t);const s=[],i=[];for(const t of e.locals){const e=u(t);i.length>0&&i[i.length-1].type===e?i[i.length-1].count++:i.push({type:e,count:1})}n(i.length,s);for(const{type:e,count:t}of i)n(t,s),s.push(e);for(let e=0;e{const{utils:r}=i(),{FunctionNode:s}=h(),{WasmFunctionEmitter:n}=ot();var a=class{constructor(){this.localCount=0}addLocal(){return this.localCount++}};for(const e of Object.getOwnPropertyNames(n.prototype))"constructor"!==e&&"addLocal"!==e&&"function"==typeof n.prototype[e]&&(a.prototype[e]=function(){return this});const o={sin:1,cos:1,tan:1,asin:1,acos:1,atan:1,atan2:2,sinh:1,cosh:1,tanh:1,asinh:1,acosh:1,atanh:1,exp:1,expm1:1,log:1,log2:1,log10:1,log1p:1,cbrt:1,pow:2,sign:1},u={abs:"f32Abs",floor:"f32Floor",ceil:"f32Ceil",sqrt:"f32Sqrt",trunc:"f32Trunc"},l={"+":"f32Add","-":"f32Sub","*":"f32Mul"},c={"+":"i32Add","-":"i32Sub","*":"i32Mul"},p={"==":"f32Eq","===":"f32Eq","!=":"f32Ne","!==":"f32Ne","<":"f32Lt",">":"f32Gt","<=":"f32Le",">=":"f32Ge"},d={"==":"i32Eq","===":"i32Eq","!=":"i32Ne","!==":"i32Ne","<":"i32LtS",">":"i32GtS","<=":"i32LeS",">=":"i32GeS"},f={"&":"i32And","|":"i32Or","^":"i32Xor","<<":"i32Shl",">>":"i32ShrS",">>>":"i32ShrU"},m={"+":"f32x4Add","-":"f32x4Sub","*":"f32x4Mul"},g={"+":"i32x4Add","-":"i32x4Sub","*":"i32x4Mul"},y={"==":"f32x4Eq","===":"f32x4Eq","!=":"f32x4Ne","!==":"f32x4Ne","<":"f32x4Lt",">":"f32x4Gt","<=":"f32x4Le",">=":"f32x4Ge"},x={"==":"i32x4Eq","===":"i32x4Eq","!=":"i32x4Ne","!==":"i32x4Ne","<":"i32x4LtS",">":"i32x4GtS","<=":"i32x4LeS",">=":"i32x4GeS"},b={"<<":"i32x4Shl",">>":"i32x4ShrS",">>>":"i32x4ShrU"},v={abs:"f32x4Abs",floor:"f32x4Floor",ceil:"f32x4Ceil",sqrt:"f32x4Sqrt",trunc:"f32x4Trunc"};function S(e){switch(e){case"Number":case"Float":case"LiteralInteger":return"f32";case"Integer":case"Boolean":return"i32";default:throw new Error(`WebAssembly backend does not yet support ${e} arguments to helper functions`)}}t.exports={WebAssemblyFunctionNode:class extends s{get readsCanFault(){return!0}get readsFaultAtOneLevel(){return!0}constructor(e,t){super(e,t),this.assembler=null,this.em=null,this.locals=null,this.depth=0,this.loopStack=null,this.usedMathImports=new Set,this.usesRandom=!1,this.readsThread=!1,this.taintedLocals=null,this.uniformity=[],this._analysisDone=!1,this._analysisPass=!1,this.vec=!1,this.vMaskDepth=0,this.vCur=-1,this.vRetMask=-1,this.vTerminated=!1,this.vInfo=null,this._vBaseX=-1}mangleFunctionName(e){return`fn_${r.sanitizeName(e)}`}getType(e){if(e&&"ConditionalExpression"===e.type){const t=this.getType(e.consequent);if("Integer"===t||"LiteralInteger"===t){const t=this.getType(e.alternate);if("Number"===t||"Float"===t)return"Number"}}return super.getType(e)}toString(){return this._analysisDone||(this._analysisDone=!0,this._analysisPass=!0,this.walkFunction(new a),this._analysisPass=!1),""}emitFunction(e){this.assembler=e;const{module:t}=e;let r;if(this.isRootKernel)r=t.addFunction("kernel",{params:[],results:[]});else{const e=this.argumentTypes.map(e=>S("LiteralInteger"===e?"Number":e)),s=[];if(this.returnType)switch(this.returnType){case"Integer":case"Boolean":s.push("i32");break;case"Number":case"Float":case"LiteralInteger":s.push("f32");break;default:throw new Error(`WebAssembly backend does not yet support helper functions returning ${this.returnType}`)}r=t.addFunction(this.mangleFunctionName(this.name),{params:e,results:s})}return this.walkFunction(r),!this.isRootKernel&&this.returnType&&r.unreachable(),r}walkFunction(e){this.em=e,this.locals=new Map,this.depth=0,this.loopStack=[],this.taintedLocals=new Set;const t=this.getJsAST();if(this.isRootKernel)for(const r of this.collectAssignedArgumentNames(t)){const t=this.argumentNames.indexOf(r),s=this.argumentTypes[t];if("Number"!==s&&"Float"!==s&&"Integer"!==s&&"Boolean"!==s)continue;const n=this.assembler?this.assembler.layout.scalars[r]:null,i=n?n.offset:0,a="Integer"===s||"Boolean"===s?"i32":"f32",o=e.addLocal(a);e.i32Const(0),"i32"===a?e.i32Load(i):e.f32Load(i),e.localSet(o),this.locals.set(r,{kind:"scalar",index:o,wtype:a,gtype:s})}if(!this.isRootKernel){for(let e=0;e{if(s&&"object"==typeof s){if(Array.isArray(s))return s.forEach(r);if("FunctionDeclaration"!==s.type||s===e){"AssignmentExpression"===s.type&&"Identifier"===s.left.type&&-1!==this.argumentNames.indexOf(s.left.name)&&t.add(s.left.name),"UpdateExpression"===s.type&&"Identifier"===s.argument.type&&-1!==this.argumentNames.indexOf(s.argument.name)&&t.add(s.argument.name);for(const e in s){if("loc"===e||"start"===e||"end"===e||"parent"===e)continue;const t=s[e];t&&"object"==typeof t&&r(t)}}}};return r(e.body),t}enterBlock(e){this.em.block(e),this.depth++}enterLoop(e){this.em.loop(e),this.depth++}enterIf(e){this.em.if_(e),this.depth++}exit(){this.em.end(),this.depth--}brTo(e){this.em.br(this.depth-e)}brIfTo(e){this.em.brIf(this.depth-e)}get loopMax(){return parseInt(this.loopMaxIterations,10)||1e3}coerce(e,t){if(e===t)return t;if("void"===e)throw new Error("cannot use a void expression as a value");switch(t){case"f32":return this.em.f32ConvertI32S(),"f32";case"i32":return"f32"===e&&this.em.i32TruncSatF32S(),"i32";case"bool":return"f32"===e?this.em.f32Const(0).f32Ne():this.em.i32Eqz().i32Eqz(),"bool";default:throw new Error(`unknown wasm value category ${t}`)}}castLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castLiteralToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}castValueToInteger(e){this.pushState("casting-to-integer");const t=this.expression(e);return this.popState("casting-to-integer"),this.coerce(t,"i32"),"i32"}castValueToFloat(e){this.pushState("casting-to-float");const t=this.expression(e);return this.popState("casting-to-float"),this.coerce(t,"f32"),"f32"}emitByType(e,t){const r=this.getType(e);return"f32"===t?"Integer"===r?this.castValueToFloat(e):"LiteralInteger"===r?this.castLiteralToFloat(e):(this.coerce(this.expression(e),"f32"),"f32"):"Number"===r||"Float"===r?this.castValueToInteger(e):"LiteralInteger"===r?this.castLiteralToInteger(e):(this.coerce(this.expression(e),"i32"),"i32")}emitCondition(e){const t=this.expression(e);if("bool"!==t)if("i32"!==t){if("f32"!==t)throw this.astErrorOutput("cannot use a void expression as a condition",e);this.em.f32Const(0).f32Ne()}else this.em.i32Eqz().i32Eqz()}statement(e){switch(e.type){case"VariableDeclaration":return this.stmtVariableDeclaration(e);case"ExpressionStatement":return this.statementExpression(e.expression);case"ReturnStatement":return this.stmtReturn(e);case"IfStatement":return this.stmtIf(e);case"ForStatement":return this.stmtFor(e);case"WhileStatement":return this.stmtWhile(e);case"DoWhileStatement":return this.stmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.castValueToFloat(n));else switch(i.valueType=u,u){case"Number":case"Float":this.setScalarLocal(o,"f32",u,()=>{"LiteralInteger"===a?this.castLiteralToFloat(n):"Integer"===a?this.castValueToFloat(n):this.coerce(this.expression(n),"f32")});break;case"Integer":this.setScalarLocal(o,"i32","Integer",()=>{"LiteralInteger"===a?this.castLiteralToInteger(n):"Number"===a||"Float"===a?this.castValueToInteger(n):this.coerce(this.expression(n),"i32")});break;case"Boolean":this.setScalarLocal(o,"i32","Boolean",()=>this.emitCondition(n));break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${u}`,e)}this.isThreadDependent(n)&&this.taintedLocals.add(o)}}setScalarLocal(e,t,r,s){let n=this.locals.get(e);n&&"scalar"===n.kind&&n.wtype===t?n.gtype=r:(n={kind:"scalar",index:this.em.addLocal(t),wtype:t,gtype:r},this.locals.set(e,n)),s(),this.em.localSet(n.index)}declareVecLocal(e,t,r,s,n){const i=parseInt(t.substring(6),10);s.valueType=t;let a=this.locals.get(e);if(!a||"vec"!==a.kind||a.n!==i){const r=[];for(let e=0;ethis.em.localSet(r.index);else{if(r||!this.isRootKernel||-1===this.argumentNames.indexOf(t))throw this.astErrorOutput(`cannot assign to "${t}"`,e);{const r=this.argumentTypes[this.argumentNames.indexOf(t)],i=this.assembler?this.assembler.layout.scalars[t]:null;if(this.assembler&&!i)throw this.astErrorOutput(`WebAssembly backend does not yet support assigning to the array argument "${t}"`,e);const a=i?i.offset:0;s="Integer"===r||"Boolean"===r?"i32":"f32",this.em.i32Const(0),n=()=>"i32"===s?this.em.i32Store(a):this.em.f32Store(a)}}if("="===e.operator){const t=this.getType(e.left),r=this.getType(e.right);"Integer"!==t&&"Integer"===r?(this.castValueToFloat(e.right),this.coerce("f32",s)):"Integer"!==t&&"LiteralInteger"===r?(this.castLiteralToFloat(e.right),this.coerce("f32",s)):"Integer"===t&&"LiteralInteger"===r?(this.castLiteralToInteger(e.right),this.coerce("i32",s)):"Integer"!==t||"Number"!==r&&"Float"!==r?this.coerce(this.expression(e.right),s):(this.castValueToInteger(e.right),this.coerce("i32",s))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.coerce(this.exprBinary(t),s)}n(),(this.isThreadDependent(e.right)||"="!==e.operator&&this.taintedLocals.has(t))&&this.taintedLocals.add(t)}emitUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const r=this.locals.get(e.argument.name);if(!r||"scalar"!==r.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const s="i32"===r.wtype,n=()=>s?this.em.i32Const(1):this.em.f32Const(1),i="++"===e.operator?s?"i32Add":"f32Add":s?"i32Sub":"f32Sub";return t?(this.em.localGet(r.index),n(),this.em[i]().localSet(r.index),"void"):(e.prefix?(this.em.localGet(r.index),n(),this.em[i]().localTee(r.index)):(this.em.localGet(r.index).localGet(r.index),n(),this.em[i]().localSet(r.index)),r.wtype)}stmtReturn(e){if(!e.argument){if(this.isRootKernel)return void this.em.return_();throw this.astErrorOutput("Unexpected return statement",e)}this.pushState("skip-literal-correction");const t=this.getType(e.argument);if(this.popState("skip-literal-correction"),this.returnType||(this.returnType="LiteralInteger"===t||"Integer"===t?"Number":t),this.isRootKernel)return this.stmtRootReturn(e,t);if(this.isSubKernel)throw this.astErrorOutput("WebAssembly backend does not yet support createKernelMap",e);switch(this.returnType){case"LiteralInteger":case"Number":case"Float":"Integer"===t?this.castValueToFloat(e.argument):"LiteralInteger"===t?this.castLiteralToFloat(e.argument):this.coerce(this.expression(e.argument),"f32");break;case"Integer":"Float"===t||"Number"===t?this.castValueToInteger(e.argument):"LiteralInteger"===t?this.castLiteralToInteger(e.argument):this.coerce(this.expression(e.argument),"i32");break;case"Boolean":this.emitCondition(e.argument);break;default:throw this.astErrorOutput(`unhandled return type ${this.returnType}`,e)}this.em.return_()}stmtRootReturn(e,t){const r=this.assembler?this.assembler.globals:{dataIndex:0},s=this.assembler?this.assembler.layout.outputOffset:0;switch(this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const t=parseInt(this.returnType.substring(6),10),n=e.argument;if("ArrayExpression"===n.type){if(n.elements.length!==t)throw this.astErrorOutput(`expected ${t} array elements to match return type ${this.returnType}`,e);for(let e=0;e1&&(t=!1);for(let e=0;e{if(e===a.length)return o&&this.emitSwitchConsequent(o),!1;const{tests:t,consequent:r}=a[e];for(let e=0;e0&&this.em.i32Or();return this.enterIf(),this.emitSwitchConsequent(r),(e+10&&(r.push({tests:s,consequent:e[n].consequent}),s=[])):t=e[n].consequent;return{groups:r,defaultConsequent:t}}collectSwitchCaseStatements(e){const t=[];for(let r=0;r{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(r);if("BreakStatement"===e.type)return!0;if("ForStatement"===e.type||"WhileStatement"===e.type||"DoWhileStatement"===e.type||"SwitchStatement"===e.type)return!1;for(const t in e)if("loc"!==t&&"range"!==t&&"parent"!==t&&r(e[t]))return!0;return!1};for(let e=0;e{const r=this.getType(t);switch(s){case"Number":case"Float":"Integer"===r?this.castValueToFloat(t):"LiteralInteger"===r?this.castLiteralToFloat(t):this.coerce(this.expression(t),"f32");break;case"Integer":"Number"===r||"Float"===r?this.castValueToInteger(t):"LiteralInteger"===r?this.castLiteralToInteger(t):this.coerce(this.expression(t),"i32");break;case"Boolean":this.emitCondition(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${s}`,e)}};return this.emitCondition(e.test),this.enterIf(n),i(e.consequent),this.em.else_(),i(e.alternate),this.exit(),"Boolean"===s?"bool":n}exprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const r=this.isAstMathFunction(e);if(t=r||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);if(this.calledFunctions.indexOf(t)<0&&this.calledFunctions.push(t),this.onFunctionCall&&this.onFunctionCall(this.name,t,e.arguments),r)return this.emitMathCall(t,e);const s=this.getType(e),n=this.lookupFunctionArgumentTypes(t)||[];for(let r=0;r{switch(this.getType(e)){case"Integer":this.castValueToFloat(e);break;case"LiteralInteger":this.castLiteralToFloat(e);break;default:this.coerce(this.expression(e),"f32")}},s=u[e];if(s)return r(t.arguments[0]),this.em[s](),"f32";switch(e){case"round":return r(t.arguments[0]),this.em.f32Const(.5).f32Add().f32Floor(),"f32";case"fround":return r(t.arguments[0]),"f32";case"min":case"max":{const s="min"===e?"f32Min":"f32Max";r(t.arguments[0]);for(let e=1;e0&&this.emitClampScalarIndex(a.dims[0]*a.dims[1]*a.dims[2]-1),this.em.i32Const(2).i32Shl(),this.em.f32Load(a.offset),"f32"}emitClampScalarIndex(e){const t=this.em.addLocal("i32");this.em.localSet(t),this.em.localGet(t).i32Const(0).localGet(t).i32Const(0).i32GeS().select(),this.em.localSet(t),this.em.localGet(t).i32Const(e).localGet(t).i32Const(e).i32LeS().select()}emitVecIndex(e,t){if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return this.em.localGet(e.indices[t.value]),"f32"}const r=this.em.addLocal("i32");this.emitIndex(t),this.em.localSet(r),this.em.localGet(e.indices[0]);for(let t=1;t{if(!e||"object"!=typeof e)return!1;switch(e.type){case"Literal":case"ThisExpression":return!1;case"Identifier":return t.has(e.name);case"MemberExpression":return e.computed||"MemberExpression"!==e.object.type||e.object.computed||!e.object.property||"thread"!==e.object.property.name?e.computed?a(e.object)||a(e.property):a(e.object):"x"===e.property.name;case"BinaryExpression":case"LogicalExpression":return a(e.left)||a(e.right);case"UnaryExpression":case"UpdateExpression":return a(e.argument);case"ConditionalExpression":return a(e.test)||a(e.consequent)||a(e.alternate);case"CallExpression":return!i.isAstMathFunction(e)||("random"===e.callee.property.name||e.arguments.some(a));case"SequenceExpression":return e.expressions.some(a);case"ArrayExpression":return e.elements.some(a);case"AssignmentExpression":return a(e.right)||"Identifier"===e.left.type&&t.has(e.left.name);default:return!0}},o=e=>{e&&!t.has(e)&&(t.add(e),n=!0)},u=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>u(e,t));switch(e.type){case"UpdateExpression":return"Identifier"===e.argument.type&&(-1!==i.argumentNames.indexOf(e.argument.name)&&(r.has(e.argument.name)||(r.add(e.argument.name),n=!0),o(e.argument.name)),t&&o(e.argument.name)),u(e.argument,t);case"AssignmentExpression":return"Identifier"===e.left.type&&(-1!==i.argumentNames.indexOf(e.left.name)&&(r.has(e.left.name)||(r.add(e.left.name),n=!0),o(e.left.name)),t&&o(e.left.name)),u(e.left,t),u(e.right,t);case"ConditionalExpression":{u(e.test,t);const r=t||a(e.test);return u(e.consequent,r),u(e.alternate,r)}case"LogicalExpression":return u(e.left,t),u(e.right,!0);default:for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const s=e[r];s&&"object"==typeof s&&u(s,t)}}}},l=(e,t)=>{if(e&&"object"==typeof e){if(Array.isArray(e))return e.forEach(e=>l(e,t));switch(e.type){case"VariableDeclarator":e.id&&"Identifier"===e.id.type&&t.push(e.id.name);break;case"AssignmentExpression":"Identifier"===e.left.type&&t.push(e.left.name);break;case"UpdateExpression":"Identifier"===e.argument.type&&t.push(e.argument.name);break;case"FunctionDeclaration":return}for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const s=e[r];s&&"object"==typeof s&&l(s,t)}}},h=(e,t)=>{if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return e.some(e=>h(e,t));switch(e.type){case"BreakStatement":case"ContinueStatement":return t;case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return!1;case"IfStatement":{const r=t||a(e.test);return!!h(e.consequent,r)||!!e.alternate&&h(e.alternate,r)}case"ConditionalExpression":{const r=t||a(e.test);return h(e.consequent,r)||h(e.alternate,r)}case"SwitchStatement":{const r=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));return e.cases.some(e=>e.consequent.some(e=>"BreakStatement"!==e.type&&h(e,r)))}default:for(const r in e){if("loc"===r||"start"===r||"end"===r||"parent"===r)continue;const s=e[r];if(s&&"object"==typeof s&&h(s,t))return!0}return!1}},c=(e,s)=>{switch(e.type){case"AssignmentExpression":if("Identifier"===e.left.type){const u=e.left.name;-1!==i.argumentNames.indexOf(u)&&(r.has(u)||(r.add(u),n=!0),o(u)),(s||a(e.right)||"="!==e.operator&&t.has(u))&&o(u)}return u(e.right,s);case"UpdateExpression":if("Identifier"===e.argument.type){const t=e.argument.name;-1!==i.argumentNames.indexOf(t)&&(r.has(t)||(r.add(t),n=!0),o(t)),s&&o(t)}return;case"SequenceExpression":return e.expressions.forEach(e=>c(e,s));default:return u(e,s)}},p=(e,t)=>{if(e)switch(e.type){case"VariableDeclaration":for(const r of e.declarations)r.init&&((t||a(r.init))&&o(r.id.name),u(r.init,t));return;case"ExpressionStatement":return c(e.expression,t);case"ReturnStatement":return t&&(s=!0),void(e.argument&&u(e.argument,t));case"IfStatement":{u(e.test,t);const r=t||a(e.test);return p(e.consequent,r),void(e.alternate&&p(e.alternate,r))}case"ForStatement":case"WhileStatement":case"DoWhileStatement":{const r=t||!!e.test&&a(e.test)||h(e.body,!1);if(r){const t=[];e.init&&l(e.init,t),l(e.body,t),e.update&&l(e.update,t),t.forEach(o)}return e.init&&("VariableDeclaration"===e.init.type?p(e.init,t):c(e.init,t)),p(e.body,r),e.update&&c(e.update,r),void(e.test&&u(e.test,r))}case"SwitchStatement":{const r=t||a(e.discriminant)||e.cases.some(e=>e.test&&a(e.test));for(const t of e.cases)for(const e of t.consequent)p(e,r);return}case"BlockStatement":return e.body.forEach(e=>p(e,t));default:return}};for(;n;)n=!1,p(e.body,!1);return{varying:t,varyingReturn:s,assignedArgs:r,exprVarying:a,hasVaryingExit:h}}vZero(){return this.em.v128ConstI32x4(0,0,0,0),this}vInnermostVaryingLoop(){const e=this.vLoopStack[this.vLoopStack.length-1];return e&&e.varying?e:null}vRecomputeCur(e){const t=this.em;t.localGet(e),-1!==this.vRetMask&&t.localGet(this.vRetMask).v128Andnot();const r=this.vInnermostVaryingLoop();r&&(-1!==r.vBrk&&t.localGet(r.vBrk).v128Andnot(),-1!==r.vCnt&&t.localGet(r.vCnt).v128Andnot()),t.localSet(this.vCur)}vLoopBodyExits(e){let t=!1,r=!1;const s=e=>{if(!(!e||"object"!=typeof e||t&&r)){if(Array.isArray(e))return e.forEach(s);switch(e.type){case"BreakStatement":return void(t=!0);case"ContinueStatement":return void(r=!0);case"ForStatement":case"WhileStatement":case"DoWhileStatement":case"FunctionDeclaration":return;case"SwitchStatement":for(const t of e.cases)for(const e of t.consequent)"BreakStatement"!==e.type&&s(e);return}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const r=e[t];r&&"object"==typeof r&&s(r)}}};return s(e),{hasBreak:t,hasContinue:r}}vSetLocal(e){const t=this.em;this.vMaskDepth>0&&t.localGet(e).localGet(this.vCur).v128Bitselect(),t.localSet(e)}vCoerce(e,t){if(e===t)return t;const r=this.em;switch(e){case"f32":case"i32":case"bool":if("vf32"===t)return this.coerce(e,"f32"),r.f32x4Splat(),t;if("vi32"===t)return this.coerce(e,"i32"),r.i32x4Splat(),t;if("vbool"===t)return this.coerce(e,"i32"),r.i32x4Splat(),this.vZero(),r.i32x4Ne(),t;break;case"vf32":if("vi32"===t)return r.i32x4TruncSatF32x4S(),t;if("vbool"===t)return r.v128ConstF32x4(0,0,0,0).f32x4Ne(),t;break;case"vi32":if("vf32"===t)return r.f32x4ConvertI32x4S(),t;if("vbool"===t)return this.vZero(),r.i32x4Ne(),t;break;case"vbool":if("vi32"===t)return r.v128ConstI32x4(1,1,1,1).v128And(),t;if("vf32"===t)return r.v128ConstI32x4(1,1,1,1).v128And().f32x4ConvertI32x4S(),t}throw new Error(`cannot convert ${e} to ${t}`)}vCastLiteralToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastLiteralToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vCastValueToInteger(e){this.pushState("casting-to-integer");const t=this.vexpr(e);return this.popState("casting-to-integer"),this.vCoerce(t,"vi32"),"vi32"}vCastValueToFloat(e){this.pushState("casting-to-float");const t=this.vexpr(e);return this.popState("casting-to-float"),this.vCoerce(t,"vf32"),"vf32"}vEmitByType(e,t){const r=this.getType(e);return"vf32"===t?"Integer"===r?this.vCastValueToFloat(e):"LiteralInteger"===r?this.vCastLiteralToFloat(e):(this.vCoerce(this.vexpr(e),"vf32"),"vf32"):"Number"===r||"Float"===r?this.vCastValueToInteger(e):"LiteralInteger"===r?this.vCastLiteralToInteger(e):(this.vCoerce(this.vexpr(e),"vi32"),"vi32")}vexprMask(e){const t=this.vexpr(e);if("vbool"!==t)return"vi32"===t?(this.vZero(),void this.em.i32x4Ne()):void("vf32"!==t?(this.coerce(t,"bool"),this.em.i32x4Splat(),this.vZero(),this.em.i32x4Ne()):this.em.v128ConstF32x4(0,0,0,0).f32x4Ne())}vstatement(e){switch(e.type){case"VariableDeclaration":return this.vstmtVariableDeclaration(e);case"ExpressionStatement":return this.vstatementExpression(e.expression);case"ReturnStatement":return this.vstmtReturn(e);case"IfStatement":return this.vstmtIf(e);case"ForStatement":return this.vstmtFor(e);case"WhileStatement":return this.vstmtWhile(e);case"DoWhileStatement":return this.vstmtDoWhile(e);case"BlockStatement":for(let t=0;tthis.vCastValueToFloat(s));switch(i.valueType=o,o){case"Number":case"Float":this.vSetVaryingScalar(n,"vf32",o,()=>{"LiteralInteger"===a?this.vCastLiteralToFloat(s):"Integer"===a?this.vCastValueToFloat(s):this.vCoerce(this.vexpr(s),"vf32")});break;case"Integer":this.vSetVaryingScalar(n,"vi32","Integer",()=>{"LiteralInteger"===a?this.vCastLiteralToInteger(s):"Number"===a||"Float"===a?this.vCastValueToInteger(s):this.vCoerce(this.vexpr(s),"vi32")});break;case"Boolean":this.vSetVaryingScalar(n,"vi32","Boolean",()=>{this.vexprMask(s),this.em.v128ConstI32x4(1,1,1,1).v128And()});break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support declaring type ${o}`,t)}}vSetVaryingScalar(e,t,r,s){let n=this.locals.get(e);n&&"vscalar"===n.kind&&n.wtype===t?n.gtype=r:(n={kind:"vscalar",index:this.em.addLocal("v128"),wtype:t,gtype:r},this.locals.set(e,n)),s(),this.vSetLocal(n.index)}vEmitArrayElement(e){switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}}vAssign(e){if("Identifier"!==e.left.type)throw this.astErrorOutput(`WebAssembly backend does not yet support assignment to ${e.left.type}`,e);const t=e.left.name,r=this.locals.get(t);if(r&&"scalar"===r.kind)return this.emitAssignment(e);if(!r||"vscalar"!==r.kind)throw this.astErrorOutput(`cannot assign to "${t}"`,e);const s=r.wtype;if("="===e.operator){const t=this.getType(e.left),r=this.getType(e.right);"Integer"!==t&&"Integer"===r?(this.vCastValueToFloat(e.right),this.vCoerce("vf32",s)):"Integer"!==t&&"LiteralInteger"===r?(this.vCastLiteralToFloat(e.right),this.vCoerce("vf32",s)):"Integer"===t&&"LiteralInteger"===r?(this.vCastLiteralToInteger(e.right),this.vCoerce("vi32",s)):"Integer"!==t||"Number"!==r&&"Float"!==r?this.vCoerce(this.vexpr(e.right),s):(this.vCastValueToInteger(e.right),this.vCoerce("vi32",s))}else{const t={type:"BinaryExpression",operator:e.operator.slice(0,-1),left:e.left,right:e.right};this.vCoerce(this.vexprBinary(t),s)}this.vSetLocal(r.index)}vUpdate(e,t){if("Identifier"!==e.argument.type)throw this.astErrorOutput("update expression needs a variable",e);const r=this.locals.get(e.argument.name);if(r&&"scalar"===r.kind)return this.emitUpdate(e,t);if(!r||"vscalar"!==r.kind)throw this.astErrorOutput(`cannot update "${e.argument.name}"`,e);const s=this.em,n="vi32"===r.wtype,i=()=>n?s.v128ConstI32x4(1,1,1,1):s.v128ConstF32x4(1,1,1,1),a="++"===e.operator?n?"i32x4Add":"f32x4Add":n?"i32x4Sub":"f32x4Sub";if(t)return s.localGet(r.index),i(),s[a](),this.vSetLocal(r.index),"void";if(e.prefix)s.localGet(r.index),i(),s[a](),this.vSetLocal(r.index),s.localGet(r.index);else{const e=s.addLocal("v128");s.localGet(r.index).localSet(e),s.localGet(r.index),i(),s[a](),this.vSetLocal(r.index),s.localGet(e)}return r.wtype}vstmtIf(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementBody(e.consequent),e.alternate&&(t.else_(),this.vstatementBody(e.alternate)),void this.exit();const r=t.addLocal("v128");this.vexprMask(e.test),t.localSet(r);const s=t.addLocal("v128");t.localGet(this.vCur).localSet(s),t.localGet(s).localGet(r).v128And().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.consequent),this.vMaskDepth--,this.exit(),e.alternate&&(t.localGet(s).localGet(r).v128Andnot().localSet(this.vCur),t.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vMaskDepth++,this.vstatementBody(e.alternate),this.vMaskDepth--,this.exit()),this.vRecomputeCur(s)}vstmtReturn(e){const t=this.em;if(!e.argument)return void this.vRetireOrReturn();this.pushState("skip-literal-correction");const r=this.getType(e.argument);switch(this.popState("skip-literal-correction"),this.returnType){case"Array(2)":case"Array(3)":case"Array(4)":{const r=parseInt(this.returnType.substring(6),10),s=e.argument,n=[];if("ArrayExpression"===s.type){if(s.elements.length!==r)throw this.astErrorOutput(`expected ${r} array elements to match return type ${this.returnType}`,e);for(let e=0;e0?i=this.vCur:-1!==this.vRetMask&&(i=t.addLocal("v128"),t.localGet(this.vRetMask).v128Not().localSet(i));const a=t.addLocal("i32");if(1===n)return t.globalGet(r.dataIndex).i32Const(2).i32Shl().localSet(a),void(-1===i?t.localGet(a).localGet(e[0]).v128Store(s,2):(t.localGet(a),t.localGet(e[0]),t.localGet(a).v128Load(s,2),t.localGet(i).v128Bitselect(),t.v128Store(s,2)));t.globalGet(r.dataIndex).i32Const(n).i32Mul().i32Const(2).i32Shl().localSet(a);for(let r=0;r<4;r++)for(let o=0;oe.test&&this.vInfo.exprVarying(e.test)),i=this.getType(t);if(!n){let n,a;switch(i){case"Float":case"Number":a=!1,n=s.addLocal("f32"),this.coerce(this.expression(t),"f32"),s.localSet(n);break;case"Integer":a=!0,n=s.addLocal("i32"),this.coerce(this.expression(t),"i32"),s.localSet(n);break;case"LiteralInteger":a=!0,n=s.addLocal("i32"),this.castLiteralToInteger(t),s.localSet(n);break;default:throw this.astErrorOutput(`Unhandled switch discriminant type "${i}"`,e)}if(1===r.length&&!r[0].test)return void this.vEmitSwitchConsequent(r[0].consequent);const{groups:o,defaultConsequent:u}=this.collectSwitchGroups(r),l=e=>{if(e===o.length)return void(u&&this.vEmitSwitchConsequent(u));const{tests:t,consequent:r}=o[e];for(let e=0;e0&&s.i32Or();this.enterIf(),this.vEmitSwitchConsequent(r),(e+10&&s.v128Or();s.localSet(p),this.vRecomputeCur(h),s.localGet(this.vCur).localGet(p).v128And().localGet(c).v128Andnot().localSet(this.vCur),s.localGet(c).localGet(p).v128Or().localSet(c),s.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(r),this.exit()}l&&(this.vRecomputeCur(h),s.localGet(this.vCur).localGet(c).v128Andnot().localSet(this.vCur),s.localGet(this.vCur).v128AnyTrue(),this.enterIf(),this.vEmitSwitchConsequent(l),this.exit()),this.vMaskDepth--,this.vRecomputeCur(h)}vEmitSwitchTest(e,t){const r=this.getType(e);t?"Number"===r||"Float"===r?this.vCastValueToInteger(e):"LiteralInteger"===r?this.vCastLiteralToInteger(e):this.vCoerce(this.vexpr(e),"vi32"):"LiteralInteger"===r?this.vCastLiteralToFloat(e):"Integer"===r?this.vCastValueToFloat(e):this.vCoerce(this.vexpr(e),"vf32")}vEmitSwitchConsequent(e){const t=this.collectSwitchCaseStatements(e),r=this.vTerminated;this.vTerminated=!1;for(let e=0;e{const r=this.getType(t);switch(n){case"Number":case"Float":"Integer"===r?this.vCastValueToFloat(t):"LiteralInteger"===r?this.vCastLiteralToFloat(t):this.vCoerce(this.vexpr(t),"vf32");break;case"Integer":"Number"===r||"Float"===r?this.vCastValueToInteger(t):"LiteralInteger"===r?this.vCastLiteralToInteger(t):this.vCoerce(this.vexpr(t),"vi32");break;case"Boolean":this.vexprMask(t);break;default:throw this.astErrorOutput(`WebAssembly backend does not yet support a ternary of type ${n}`,e)}},a="Integer"===n?"vi32":"Boolean"===n?"vbool":"vf32";if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf("v128"),i(e.consequent),t.else_(),i(e.alternate),this.exit(),a;const o=t.addLocal("v128");this.vexprMask(e.test),t.localSet(o);const u=t.addLocal("v128");t.localGet(this.vCur).localSet(u);const l=t.addLocal("v128"),h=t.addLocal("v128");return t.localGet(u).localGet(o).v128And().localSet(this.vCur),this.vMaskDepth++,i(e.consequent),t.localSet(l),t.localGet(u).localGet(o).v128Andnot().localSet(this.vCur),i(e.alternate),t.localSet(h),this.vMaskDepth--,t.localGet(u).localSet(this.vCur),t.localGet(l).localGet(h).localGet(o).v128Bitselect(),a}vTernaryStatement(e){const t=this.em;if(!this.vInfo.exprVarying(e.test))return this.emitCondition(e.test),this.enterIf(),this.vstatementExpression(e.consequent),t.else_(),this.vstatementExpression(e.alternate),void this.exit();const r=t.addLocal("v128");this.vexprMask(e.test),t.localSet(r);const s=t.addLocal("v128");t.localGet(this.vCur).localSet(s),t.localGet(s).localGet(r).v128And().localSet(this.vCur),this.vMaskDepth++,this.vstatementExpression(e.consequent),t.localGet(s).localGet(r).v128Andnot().localSet(this.vCur),this.vstatementExpression(e.alternate),this.vMaskDepth--,t.localGet(s).localSet(this.vCur)}vexprCall(e){if(!e.callee)throw this.astErrorOutput("Unknown CallExpression",e);if("MemberExpression"===e.callee.type&&"this.color"===this.getVariableSignature(e.callee,!0))throw this.astErrorOutput("WebAssembly backend does not yet support graphical mode (this.color)",e);let t=null;const r=this.isAstMathFunction(e);if(t=r||e.callee.object&&"ThisExpression"===e.callee.object.type?e.callee.property.name:"SequenceExpression"!==e.callee.type||"Literal"!==e.callee.expressions[0].type||isNaN(e.callee.expressions[0].raw)?e.callee.name:e.callee.expressions[1].property.name,!t)throw this.astErrorOutput("Unhandled function, couldn't find name",e);return r?this.vMathCall(t,e):this.vUserCall(t,e)}vUserCall(e,t){const r=this.em,s=this.assembler.helperInfo||{readsThread:!1,usesRandom:!1},n=this.assembler.globals,i=this.getType(t),a=this.lookupFunctionArgumentTypes(e)||[],o=[];for(let s=0;s0&&r.i32Const(t).i32Add(),r.globalSet(n.threadX)),s.usesRandom&&r.localGet(c).i32x4ExtractLane(t).globalSet(n.pcgState);for(const e of o)r.localGet(e.index),"vi32"===e.wtype?r.i32x4ExtractLane(t):r.f32x4ExtractLane(t);r.call(this.mangleFunctionName(e)),"void"!==u&&r.localSet(l),s.usesRandom&&r.localGet(c).globalGet(n.pcgState).i32x4ReplaceLane(t).localSet(c),"void"!==u&&(0===t?(r.localGet(l),"i32"===u?r.i32x4Splat():r.f32x4Splat(),r.localSet(h)):(r.localGet(h).localGet(l),"i32"===u?r.i32x4ReplaceLane(t):r.f32x4ReplaceLane(t),r.localSet(h)))}return s.readsThread&&r.localGet(this._vBaseX).globalSet(n.threadX),s.usesRandom&&(r.localGet(c).globalGet(n.pcgStateV),this.vMaskDepth>0?r.localGet(this.vCur):r.v128ConstI32x4(-1,-1,-1,-1),r.v128Bitselect().globalSet(n.pcgStateV)),"void"===u?"void":(r.localGet(h),"i32"===u?"vi32":"vf32")}vMathCall(e,t){const r=this.em;if("random"===e)return this.usesRandom=!0,this.vMaskDepth>0?r.localGet(this.vCur):r.v128ConstI32x4(-1,-1,-1,-1),r.call("pcg_random_v"),"vf32";const s=e=>{switch(this.getType(e)){case"Integer":this.vCastValueToFloat(e);break;case"LiteralInteger":this.vCastLiteralToFloat(e);break;default:this.vCoerce(this.vexpr(e),"vf32")}},n=v[e];if(n)return s(t.arguments[0]),r[n](),"vf32";switch(e){case"round":return s(t.arguments[0]),r.v128ConstF32x4(.5,.5,.5,.5).f32x4Add().f32x4Floor(),"vf32";case"fround":return s(t.arguments[0]),"vf32";case"min":case"max":{const n="min"===e?"f32x4Min":"f32x4Max";s(t.arguments[0]);for(let e=1;e{r.localGet(e.indices[t]),"vec"===e.kind&&r.f32x4Splat()};if("Literal"===t.type&&Number.isInteger(t.value)){if(t.value<0||t.value>=e.n)throw this.astErrorOutput(`index ${t.value} out of range for Array(${e.n})`,t);return s(t.value),"vf32"}const n=r.addLocal("v128");this.vEmitIndex(t),r.localSet(n);const i=r.addLocal("v128");s(0),r.localSet(i);for(let t=1;tthis.isThreadDependent(e));switch(e.type){case"MemberExpression":{const t=this.getVariableSignature(e);if("this.thread.value"===t||"value.thread.value"===t)return"x"===e.property.name;break}case"CallExpression":if(this.isAstMathFunction(e)){if("random"===e.callee.property.name)return!0;break}return!0;case"Identifier":return!!this.taintedLocals&&this.taintedLocals.has(e.name);case"ThisExpression":return!1}for(const t in e){if("loc"===t||"start"===t||"end"===t||"parent"===t)continue;const r=e[t];if(r&&"object"==typeof r&&this.isThreadDependent(r))return!0}return!1}recordUniformity(e,t){this._analysisPass&&this.uniformity.push({kind:e,threadDependent:!t||this.isThreadDependent(t)})}}}}),lt=e((e,t)=>{let r=null;try{r=f()}catch(e){}const s="function"==typeof Worker;const n="\nvar entries = {};\nvar pipelines = {};\nfunction handleMessage(message, post) {\n if (message.type === 'setup') {\n var imports = { env: { memory: message.memory } };\n for (var i = 0; i < message.mathImports.length; i++) {\n imports.env['math_' + message.mathImports[i]] = Math[message.mathImports[i]];\n }\n var instance = new WebAssembly.Instance(message.module, imports);\n entries[message.id] = {\n run: instance.exports.run,\n runSimd: instance.exports.run_simd || null,\n sizeX: message.sizeX\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'pipelineSetup') {\n var instances = [];\n for (var i = 0; i < message.modules.length; i++) {\n var imports = { env: { memory: message.memory } };\n var math = message.moduleMathImports[i];\n for (var j = 0; j < math.length; j++) {\n imports.env['math_' + math[j]] = Math[math[j]];\n }\n instances.push(new WebAssembly.Instance(message.modules[i], imports));\n }\n var steps = [];\n for (var i = 0; i < message.steps.length; i++) {\n var exported = instances[message.steps[i].module].exports;\n steps.push({\n run: exported.run,\n runSimd: exported.run_simd || null,\n sizeX: message.steps[i].sizeX\n });\n }\n pipelines[message.id] = {\n steps: steps,\n i32: new Int32Array(message.memory.buffer),\n countIndex: message.countIndex,\n genIndex: message.genIndex,\n abortIndex: message.abortIndex\n };\n post({ type: 'ready', id: message.id });\n } else if (message.type === 'release') {\n delete entries[message.id];\n delete pipelines[message.id];\n } else if (message.type === 'run') {\n var entry = entries[message.id];\n var start = message.start;\n var end = message.end;\n var seed = message.seed;\n if (entry.runSimd && (entry.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) entry.runSimd(start, quadEnd, seed);\n if (quadEnd < end) entry.run(quadEnd, end, seed);\n } else {\n entry.run(start, end, seed);\n }\n post({ type: 'done', taskId: message.taskId });\n } else if (message.type === 'pipelineRun') {\n var pipeline = pipelines[message.id];\n var i32 = pipeline.i32;\n var gen = message.baseGen;\n var aborted = false;\n for (var s = 0; s < pipeline.steps.length && !aborted; s++) {\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n var step = pipeline.steps[s];\n var start = message.ranges[s * 2];\n var end = message.ranges[s * 2 + 1];\n var seed = message.seeds[s];\n if (end > start) {\n if (step.runSimd && (step.sizeX & 3) === 0 && (start & 3) === 0) {\n var quadEnd = end - ((end - start) & 3);\n if (quadEnd > start) step.runSimd(start, quadEnd, seed);\n if (quadEnd < end) step.run(quadEnd, end, seed);\n } else {\n step.run(start, end, seed);\n }\n }\n gen++;\n if (Atomics.add(i32, pipeline.countIndex, 1) + 1 === message.workerCount) {\n Atomics.store(i32, pipeline.countIndex, 0);\n Atomics.store(i32, pipeline.genIndex, gen);\n Atomics.notify(i32, pipeline.genIndex);\n } else {\n for (;;) {\n if (Atomics.load(i32, pipeline.genIndex) >= gen) break;\n if (Atomics.load(i32, pipeline.abortIndex)) {\n aborted = true;\n break;\n }\n Atomics.wait(i32, pipeline.genIndex, gen - 1, 100);\n }\n }\n }\n post({ type: 'done', taskId: message.taskId, aborted: aborted });\n }\n}\nif (typeof self !== 'undefined' && typeof postMessage === 'function') {\n self.onmessage = function(event) {\n handleMessage(event.data, function(message) { postMessage(message); });\n };\n} else {\n var parentPort = require('worker_threads').parentPort;\n parentPort.on('message', function(message) {\n handleMessage(message, function(reply) { parentPort.postMessage(reply); });\n });\n}\n";t.exports={WebAssemblyWorkerPool:class{constructor(e){this.size=e||function(){if("undefined"!=typeof navigator&&navigator.hardwareConcurrency)return navigator.hardwareConcurrency;if(r&&"function"==typeof r.cpus){const e=r.cpus().length;if(e)return e}return 4}(),this.workers=[],this.destroyed=!1,this.dispatchCount=0,this.lastDispatch=null,this._taskId=0}get liveWorkerCount(){let e=0;for(const t of this.workers)t.dead||e++;return e}_spawn(){const e={handle:null,dead:!1,state:{setup:new Set,settingUp:new Map,pending:new Map},fail:null,die:null},t=e.state;e.fail=e=>{for(const r of t.settingUp.values())r.reject(e);t.settingUp.clear();for(const r of t.pending.values())r.reject(e);t.pending.clear()},e.die=t=>{if(!e.dead&&(e.dead=!0,e.fail(t),e.handle&&"function"==typeof e.handle.terminate))try{e.handle.terminate()}catch(e){}};const r=r=>{if("ready"===r.type){const s=t.settingUp.get(r.id);s&&(t.settingUp.delete(r.id),t.setup.add(r.id),this._updateRef(e),s.resolve())}else if("done"===r.type){const s=t.pending.get(r.taskId);s&&(t.pending.delete(r.taskId),this._updateRef(e),s.resolve())}};let i;if(s){const t=URL.createObjectURL(new Blob([n],{type:"text/javascript"}));i=new Worker(t),URL.revokeObjectURL(t),i.onmessage=e=>r(e.data),i.onerror=t=>e.die(new Error(t.message||"WebAssembly worker error"))}else{const{Worker:t}=f();i=new t(n,{eval:!0}),i.on("message",r),i.on("error",t=>e.die(t)),i.on("exit",t=>{e.die(new Error(`WebAssembly worker exited with code ${t}`))}),i.unref()}return e.handle=i,e}_worker(e){for(;this.workers.length<=e;)this.workers.push(this._spawn());return this.workers[e].dead&&(this.workers[e]=this._spawn()),this.workers[e]}_updateRef(e){!e.dead&&e.handle&&"function"==typeof e.handle.ref&&(e.state.settingUp.size+e.state.pending.size>0?e.handle.ref():e.handle.unref())}_ensureSetup(e,t){if(e.state.setup.has(t.id))return Promise.resolve();let r=e.state.settingUp.get(t.id);return r||(r={},r.promise=new Promise((e,t)=>{r.resolve=e,r.reject=t}),e.state.settingUp.set(t.id,r),this._updateRef(e),e.handle.postMessage(t.pipeline?{type:"pipelineSetup",id:t.id,memory:t.memory,modules:t.modules,moduleMathImports:t.moduleMathImports,steps:t.steps,countIndex:t.countIndex,genIndex:t.genIndex,abortIndex:t.abortIndex}:{type:"setup",id:t.id,module:t.module,memory:t.memory,mathImports:t.mathImports,sizeX:t.sizeX})),r.promise}dispatch(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:t.length,ranges:t.map(e=>[e.start,e.end])};const r=t.map((t,r)=>{const s=this._worker(r);return this._ensureSetup(s,e).then(()=>new Promise((r,n)=>{if(s.dead)return void n(new Error("WebAssembly worker died before the task could run"));const i=++this._taskId;s.state.pending.set(i,{resolve:r,reject:n}),this._updateRef(s),s.handle.postMessage({type:"run",id:e.id,taskId:i,start:t.start,end:t.end,seed:t.seed})}))});return Promise.all(r).then(()=>{})}dispatchPipeline(e,t){if(this.destroyed)return Promise.reject(new Error("WebAssembly worker pool has been destroyed"));this.dispatchCount++,this.lastDispatch={workerCount:e.workerCount,ranges:e.workerRanges.map(e=>e.slice())};const r=[];for(let s=0;snew Promise((r,i)=>{if(n.dead)return void i(new Error("WebAssembly worker died before the task could run"));const a=++this._taskId;n.state.pending.set(a,{resolve:r,reject:i}),this._updateRef(n),n.handle.postMessage({type:"pipelineRun",id:e.id,taskId:a,ranges:e.workerRanges[s],seeds:t.seeds,baseGen:t.baseGen,workerCount:e.workerCount})})))}return Promise.all(r).then(()=>{})}release(e){if(!this.destroyed)for(const t of this.workers){if(t.dead)continue;t.state.setup.delete(e);const r=t.state.settingUp.get(e);r&&(t.state.settingUp.delete(e),r.reject(new Error("WebAssembly kernel entry released during setup")),this._updateRef(t)),t.handle.postMessage({type:"release",id:e})}}destroy(){if(this.destroyed)return;this.destroyed=!0;const e=new Error("WebAssembly worker pool has been destroyed");for(const t of this.workers)t.dead=!0,t.fail(e),t.handle.terminate();this.workers=[]}}}}),ht=e((e,t)=>{const{Kernel:r}=a(),{FunctionBuilder:n}=u(),{WebAssemblyFunctionNode:o}=ut(),{WasmModuleBuilder:l}=ot(),{WebAssemblyWorkerPool:h}=lt(),{utils:c}=i(),{Input:p}=s(),d=Object.freeze({kernelMap:!1,isIntegerDivisionAccurate:!0,isSpeedTacticSupported:!1,isTextureFloat:!0,isDrawBuffers:!1,kernelMapSize:0,channelCount:1,maxTextureSize:1/0,isFloatRead:!0});let f=null,m=null,g=1;t.exports={WebAssemblyKernel:class e extends r{static get isSupported(){return"object"==typeof WebAssembly&&null!==WebAssembly&&WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0]))}static get isSIMDSupported(){if(null===f)try{const e=new l;e.addFunction("t",{params:[],results:[]}).v128ConstI32x4(0,0,0,0).drop(),f=WebAssembly.validate(e.toBytes())}catch(e){f=!1}return f}static get isThreadsSupported(){if(null===m)try{if("undefined"==typeof SharedArrayBuffer)m=!1;else{const e=new l;e.addMemoryImport(1,1,!0);const t=new WebAssembly.Memory({initial:1,maximum:1,shared:!0});new WebAssembly.Instance(new WebAssembly.Module(e.toBytes()),{env:{memory:t}}),m=!0}}catch(e){m=!1}return m}static isContextMatch(e){return!1}static getFeatures(){return d}static get features(){return d}static get mode(){return"webasm"}static getSignature(e,t){return"webasm"+(t.length>0?":"+t.join(","):"")}static destroyContext(e){}static dispatchSpans(e,t,r,s,n){if(!t||0===r)return e(0,r,n),"scalar";if(!(3&s))return t(0,r,n),"simd";const i=-4&s,a=r/s;for(let r=0;r0&&t(a,a+i,n),e(a+i,a+s,n)}return i>0?"simd+scalar-tail":"scalar"}static nativeFunctionArguments(){throw new Error("WebAssembly backend does not yet support native functions")}static nativeFunctionReturnType(){throw new Error("WebAssembly backend does not yet support native functions")}static combineKernels(){throw new Error("WebAssembly backend does not yet support combineKernels")}constructor(e,t){super(e,t),this.poolSize=null,this.mergeSettings(e.settings||t),null===this.precision&&(this.precision="single"),this.threadDim=null,this.componentCount=1,this.moduleCacheLimit=8,this.functionBuilder=null,this.tracedFunctions=null,this.usesRandom=!1,this.usedMathImports=null,this._moduleCache=new Map,this._active=null,this._lastRunPath=null,this._pool=null,this._threadedTail=Promise.resolve(),this._threadedBusy=0,this._threadedEpoch=0}initCanvas(){return this.graphical&&"undefined"!=typeof document?document.createElement("canvas"):null}initContext(){return null}initPlugins(e){return[]}setOutput(e){const t=this.toKernelOutput(e);if(this.built&&!this.dynamicOutput)throw new Error("Resizing a kernel with dynamicOutput: false is not possible");return this.output=t,this}toString(){throw new Error("WebAssembly backend does not yet support toString")}build(){if(this.built)return;if(this.gpu&&this.gpu.kernels&&-1===this.gpu.kernels.indexOf(this)&&this.gpu.kernels.push(this),this.graphical)return this.requestFallback(arguments,"graphical mode is not supported on the webasm backend");if(this.subKernels&&this.subKernels.length>0)return this.requestFallback(arguments,"kernel maps are not supported on the webasm backend");this.setupConstants(),this.setupArguments(arguments);for(let e=0;e{this.translateSource()?(t=!1,this.buildSignature(arguments),this._instantiate(this._entryKey(arguments),arguments)):t=!0}),t)return this.requestFallback(arguments,`return type ${this.returnType} is not supported on the webasm backend`);this.built=!0}validateSettings(e){if(!this.output||0===this.output.length){if(1!==e.length)throw new Error("Auto output only supported for kernels with only one input");const t=c.getVariableType(e[0],this.strictIntegers);if("Array"!==t)throw new Error("Auto output not supported for input type: "+t);this.output=Array.from(c.getDimensions(e[0]))}this.checkOutput()}translateSource(){const e=this.functionBuilder=n.fromKernel(this,o);switch(this.tracedFunctions=e.traceFunctionCalls("kernel",[]),this.returnType||(this.returnType=e.getKernelResultType()),this.returnType){case"Number":case"Float":case"Integer":case"LiteralInteger":this.componentCount=1;break;case"Array(2)":this.componentCount=2;break;case"Array(3)":this.componentCount=3;break;case"Array(4)":this.componentCount=4;break;default:return!1}this.usesRandom=!1,this.usedMathImports=new Set;for(const t of this.tracedFunctions){const r=e.functionMap[t];if(r){r.usesRandom&&(this.usesRandom=!0);for(const e of r.usedMathImports)this.usedMathImports.add(e)}}return!0}computeLayout(e){const t=e=>16*Math.ceil(e/16);let r=0;const s={},n={};for(let i=0;i=4096}_entryKey(e){return this._computeSizeSignature(e)+(this._threadable()?"|shared":"")}_assembleModule(t,r,s){const n=new l,i=t.totalBytes||t.outputOffset+r*this.componentCount*4,a=Math.ceil(i/65536)+16,o=Math.max(a,4096);n.addMemoryImport(a,o,s);const u=Array.from(this.usedMathImports).sort();for(const e of u){const t="pow"===e||"atan2"===e?["f32","f32"]:["f32"];n.addFuncImport("math_"+e,t,["f32"])}const h={threadX:n.addGlobal("i32",!0,0),threadY:n.addGlobal("i32",!0,0),threadZ:n.addGlobal("i32",!0,0),dataIndex:n.addGlobal("i32",!0,0)};this.usesRandom&&(h.pcgState=n.addGlobal("i32",!0,0),this._emitPcgRandom(n,h.pcgState));const c={module:n,layout:t,globals:h};for(let e=this.tracedFunctions.length-1;e>=0;e--){const t=this.tracedFunctions[e];if("kernel"===t)continue;const r=this.functionBuilder.functionMap[t];r&&(r.output=this.output,r.emitFunction(c))}this.functionBuilder.functionMap.kernel.output=this.output,this.functionBuilder.functionMap.kernel.emitFunction(c);const[p,d]=this.threadDim,f=n.addFunction("run",{params:["i32","i32","i32"],locals:["i32"]});if(f.localGet(0).localSet(3),1===this.output.length?(f.i32Const(0).globalSet(h.threadY),f.i32Const(0).globalSet(h.threadZ)):2===this.output.length&&f.i32Const(0).globalSet(h.threadZ),f.block(),f.localGet(3).localGet(1).i32GeS().brIf(0),f.loop(),f.localGet(3).globalSet(h.dataIndex),1===this.output.length?f.localGet(3).globalSet(h.threadX):2===this.output.length?(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().globalSet(h.threadY)):(f.localGet(3).i32Const(p).i32RemU().globalSet(h.threadX),f.localGet(3).i32Const(p).i32DivU().i32Const(d).i32RemU().globalSet(h.threadY),f.localGet(3).i32Const(p*d).i32DivU().globalSet(h.threadZ)),this.usesRandom&&f.localGet(2).localGet(3).i32Const(-1640531527).i32Mul().i32Add().i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(h.pcgState),f.call("kernel"),f.localGet(3).i32Const(1).i32Add().localSet(3),f.localGet(3).localGet(1).i32LtS().brIf(0),f.end(),f.end(),n.exportFunction("run"),e.isSIMDSupported){this.usesRandom&&(h.pcgStateV=n.addGlobal("v128",!0,0),this._emitPcgRandomVector(n,h.pcgStateV));let e=null;for(const t of this.tracedFunctions){if("kernel"===t)continue;const r=this.functionBuilder.functionMap[t];r&&(e||(e={readsThread:!1,usesRandom:!1}),r.readsThread&&(e.readsThread=!0),r.usesRandom&&(e.usesRandom=!0))}c.helperInfo=e,this.functionBuilder.functionMap.kernel.emitVectorFunction(c),this._emitRunSimd(n,h),n.exportFunction("run_simd")}return{bytes:n.toBytes(),initial:a,maximum:o}}_emitRunSimd(e,t){const[r,s]=this.threadDim,n=e.addFunction("run_simd",{params:["i32","i32","i32"],locals:["i32"]});n.localGet(0).localSet(3),1===this.output.length?(n.i32Const(0).globalSet(t.threadY),n.i32Const(0).globalSet(t.threadZ)):2===this.output.length&&n.i32Const(0).globalSet(t.threadZ),n.block(),n.localGet(3).localGet(1).i32GeS().brIf(0),n.loop(),n.localGet(3).globalSet(t.dataIndex),1===this.output.length?n.localGet(3).globalSet(t.threadX):2===this.output.length?(n.localGet(3).i32Const(r).i32RemU().globalSet(t.threadX),n.localGet(3).i32Const(r).i32DivU().globalSet(t.threadY)):(n.localGet(3).i32Const(r).i32RemU().globalSet(t.threadX),n.localGet(3).i32Const(r).i32DivU().i32Const(s).i32RemU().globalSet(t.threadY),n.localGet(3).i32Const(r*s).i32DivU().globalSet(t.threadZ)),this.usesRandom&&(n.localGet(3).i32x4Splat().v128ConstI32x4(0,1,2,3).i32x4Add(),n.v128ConstI32x4(-1640531527,-1640531527,-1640531527,-1640531527).i32x4Mul(),n.localGet(2).i32x4Splat().i32x4Add(),n.v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul(),n.v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add(),n.globalSet(t.pcgStateV)),n.call("kernel_simd"),n.localGet(3).i32Const(4).i32Add().localSet(3),n.localGet(3).localGet(1).i32LtS().brIf(0),n.end(),n.end()}_emitPcgRandomVector(e,t){const r=e.addFunction("pcg_random_v",{params:["v128"],results:["v128"]}),s=r.addLocal("v128"),n=r.addLocal("i32");r.globalGet(t).v128ConstI32x4(747796405,747796405,747796405,747796405).i32x4Mul().v128ConstI32x4(-1403630843,-1403630843,-1403630843,-1403630843).i32x4Add().globalGet(t).localGet(0).v128Bitselect().globalSet(t),r.globalGet(t).localSet(s),r.localGet(s).i32x4ExtractLane(0).localSet(n),r.localGet(n).localGet(n).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4Splat();for(let e=1;e<4;e++)r.localGet(s).i32x4ExtractLane(e).localSet(n),r.localGet(n).localGet(n).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().i32x4ReplaceLane(e);r.localGet(s).v128Xor(),r.v128ConstI32x4(277803737,277803737,277803737,277803737).i32x4Mul();const i=r.addLocal("v128");r.localTee(i),r.i32Const(22).i32x4ShrU().localGet(i).v128Xor(),r.i32Const(8).i32x4ShrU(),r.f32x4ConvertI32x4U(),r.v128ConstF32x4(16777216,16777216,16777216,16777216).f32x4Div()}_emitPcgRandom(e,t){const r=e.addFunction("pcg_random",{params:[],results:["f32"]}),s=r.addLocal("i32");r.globalGet(t).i32Const(747796405).i32Mul().i32Const(-1403630843).i32Add().globalSet(t),r.globalGet(t).globalGet(t).i32Const(28).i32ShrU().i32Const(4).i32Add().i32ShrU().globalGet(t).i32Xor().i32Const(277803737).i32Mul().localTee(s),r.i32Const(22).i32ShrU().localGet(s).i32Xor().i32Const(8).i32ShrU().f32ConvertI32U().f32Const(16777216).f32Div()}_releaseEntry(e){const t=()=>{e.instance=null,e.module=null,e.memory=null,e.run=null,e.runSimd=null,e.f32=null,e.i32=null,e.bytes=null};if(e.shared&&this._pool){const r=this._pool;this._threadedTail.then(()=>{r.release(e.id),t()},t)}else t()}_instantiate(e,t){let r=this._moduleCache.get(e);if(r&&(this._moduleCache.delete(e),this._moduleCache.set(e,r)),!r){const s=this._threadable(),n=this.computeLayout(t),[i,a,o]=this.threadDim,u=i*a*o,{bytes:l,initial:h,maximum:d}=this._assembleModule(n,u,s);if(!WebAssembly.validate(l))throw new Error("WebAssembly backend: generated module failed validation (internal error)");const f=s?new WebAssembly.Memory({initial:h,maximum:d,shared:!0}):new WebAssembly.Memory({initial:h,maximum:d}),m={env:{memory:f}};for(const e of this.usedMathImports)m.env["math_"+e]=Math[e];const y=new WebAssembly.Module(l),x=new WebAssembly.Instance(y,m);r={id:g++,sizeSignature:e,shared:s,layout:n,cells:u,bytes:l,module:y,memory:f,mathImports:Array.from(this.usedMathImports).sort(),sizeX:i,instance:x,run:x.exports.run,runSimd:x.exports.run_simd||null,f32:new Float32Array(f.buffer),i32:new Int32Array(f.buffer)};for(const e in n.constantArrays){const t=n.constantArrays[e],s=this.constants[e];c.flattenTo(s instanceof p?s.value:s,r.f32.subarray(t.offset/4,t.offset/4+t.flatLength))}for(this._moduleCache.set(e,r);this._moduleCache.size>Math.max(this.moduleCacheLimit,1);){const e=this._moduleCache.keys().next().value,t=this._moduleCache.get(e);this._moduleCache.delete(e),this._releaseEntry(t)}}this._active=r}checkArgumentTypes(e){if(super.checkArgumentTypes(e),!this.argumentTypes)return;const t=Math.min(e.length,this.argumentTypes.length);for(let r=0;r>>0:4294967296*Math.random()>>>0),l|=0,this._lastRunPath=e.dispatchSpans(o,u,n,t[0],l);const h=s.outputOffset/4,d=i.slice(h,h+n*this.componentCount);return this._shapeOutput(d,Array.from(this.output),this.componentCount)}_runThreaded(e){const t=this._active,{layout:r,cells:s}=t,n=0===this._threadedBusy;let i=null,a=null;if(n){for(const s in r.arrays){const n=r.arrays[s],i=e[n.index];c.flattenTo(i instanceof p?i.value:i,t.f32.subarray(n.offset/4,n.offset/4+n.flatLength))}for(const s in r.scalars){const n=r.scalars[s],i=e[n.index];"Integer"===n.type?t.i32[n.offset/4]=0|i:"Boolean"===n.type?t.i32[n.offset/4]=i?1:0:t.f32[n.offset/4]=i}}else{i=[];for(const t in r.arrays){const s=r.arrays[t],n=e[s.index],a=new Float32Array(s.flatLength);c.flattenTo(n instanceof p?n.value:n,a),i.push({record:s,flat:a})}a=[];for(const t in r.scalars){const s=r.scalars[t];a.push({record:s,value:e[s.index]})}}let o=0;this.usesRandom&&(o=null!==this.randomSeed?this.randomSeed>>>0:4294967296*Math.random()>>>0),o|=0,this._pool||(this._pool=new h(this.poolSize||void 0));const u=this._pool,l=this.componentCount,d=Array.from(this.output);this._threadedBusy++;const f=this._threadedTail.then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");if(i){for(let e=0;e=s)break;h.push({start:r,end:t===e-1?s:Math.min(r+n,s),seed:o})}return this._lastRunPath="threaded",u.dispatch(t,h).then(()=>{if(!t.f32)throw new Error("WebAssembly kernel was destroyed");const e=r.outputOffset/4,n=t.f32.slice(e,e+s*l);return this._shapeOutput(n,d,l)})}),m=this._threadedEpoch,g=()=>{this._threadedEpoch===m&&this._threadedBusy--};return this._threadedTail=f.then(g,g),f}_shapeOutput(e,t,r){const[s,n,i]=[t[0],t[1]||1,t[2]||1];if(1===r)switch(t.length){case 1:return c.erectMemoryOptimizedFloat(e,s);case 2:return c.erectMemoryOptimized2DFloat(e,s,n);default:return c.erectMemoryOptimized3DFloat(e,s,n,i)}const a=r,o=t=>{const r=new Array(s);for(let n=0;n{const{utils:r}=i(),{Input:n}=s(),{WebAssemblyKernel:a}=ht(),{WebAssemblyWorkerPool:o}=lt(),u=["Array","Input","Number","Float","Integer","Boolean"];let l=1;var h=class extends Error{constructor(e,t){super(e),this.isFusionFallback=!0,this.recompilable=Boolean(t)}};function c(e){return e&&"function"==typeof e.toArray?e.toArray():e}function p(e){const t=e instanceof n?Array.from(e.size):Array.from(r.getDimensions(e));for(;t.length<3;)t.push(1);return t}function d(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}t.exports={WebAssemblyPipelineExecutor:class e{static compile(t,r,s){for(let e=0;er.getVariableType(e,h)).join(",");let d=s.get(p);if(!d){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(o.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=o.clone.kernel;this._prepareKernel(e,l),d={id:s.size,kernel:e,constantRegions:null},s.set(p,d)}u[n]=d,c[n]=l}for(let e=0;e{const t=p;return p=(e=>16*Math.ceil(e/16))(p+e),t};let f=0,m=-1;if(!this.pipeline._threadsDisabled&&a.isThreadsSupported){let e=0;for(let r=0;re&&(e=n)}const r=new o;f=Math.min(r.size,Math.ceil(e/4096)),f>1?(this.threaded=!0,this.kind="fused-threaded",this.pool=r,m=d(12)):r.destroy()}const g=new Map,y=new Map,x=new Map,b=[],v=[],S=[],T=new Array(t.steps.length);for(let e=0;e${i}`;let l=E.get(o);if(!l){const a={arrays:n.arrays,scalars:n.scalars,constantArrays:r.constantRegions,outputOffset:i,totalBytes:_},u=w[t.steps[e].outputBuffer].cells,h=s._assembleModule(a,u,this.threaded);null===this.memory&&(this.memory=this.threaded?new WebAssembly.Memory({initial:h.initial,maximum:h.maximum,shared:!0}):new WebAssembly.Memory({initial:h.initial,maximum:h.maximum}),this.f32=new Float32Array(this.memory.buffer),this.i32=new Int32Array(this.memory.buffer));const c={env:{memory:this.memory}};for(const e of s.usedMathImports)c.env["math_"+e]=Math[e];const p=new WebAssembly.Module(h.bytes),d=new WebAssembly.Instance(p,c);l={run:d.exports.run,runSimd:d.exports.run_simd||null,moduleIndex:k.length},k.push(p),C.push(Array.from(s.usedMathImports).sort()),E.set(o,l)}I[e]={run:l.run,runSimd:l.runSimd,moduleIndex:l.moduleIndex,cells:w[t.steps[e].outputBuffer].cells,sizeX:s.threadDim[0],usesRandom:s.usesRandom,randomSeed:s.randomSeed}}if(this.threaded){const e=[];for(let r=0;r=t?(s[2*e]=0,s[2*e+1]=0):(s[2*e]=i,s[2*e+1]=r===f-1?t:Math.min(i+n,t))}e.push(s)}this._entry={id:"pipeline:"+l++,pipeline:!0,memory:this.memory,modules:k,moduleMathImports:C,steps:I.map(e=>({module:e.moduleIndex,sizeX:e.sizeX})),countIndex:m/4,genIndex:m/4+1,abortIndex:m/4+2,workerCount:f,workerRanges:e}}for(let e=0;e{const r=e.binding;if("step"===r.source){const e=r.step,s=w[t.steps[e].outputBuffer],n=u[e].kernel;return{kind:"step",base:s.offset/4,count:s.cells*n.componentCount,output:t.steps[e].output,componentCount:n.componentCount,kernel:n}}return"pipelineArg"===r.source?{kind:"arg",index:r.index}:{kind:"literal",value:r.value}}),this._stepRuns=I,this._argArrayRegions=g,this._argScalarSlots=y,this._scratch=null}_representativeArgs(e,t){const r=new Array(e.argBindings.length);for(let s=0;s>>0:4294967296*Math.random()>>>0):0}_executeThreaded(e){const t=this._entry,r=this.i32,s=this._stepRuns.map(e=>this._drawSeed(e));this._lastRunAborted&&(Atomics.store(r,t.countIndex,0),Atomics.store(r,t.abortIndex,0),this._lastRunAborted=!1,this._abortError=null);const n=Atomics.load(r,t.genIndex),i=n+this._stepRuns.length;return this.pool.dispatchPipeline(t,{baseGen:n,seeds:s}).then(null,e=>this._abort(e)),this._waitForGeneration(i).then(()=>this._readResults(e))}_waitForGeneration(e){const t=this.i32,r=this._entry.genIndex,s="function"==typeof Atomics.waitAsync?Atomics.waitAsync:null;return new Promise((n,i)=>{const a="function"==typeof setInterval?setInterval(()=>{},200):null,o=(e,t)=>{null!==a&&clearInterval(a),e(t)},u=this._entry.countIndex;let l=Atomics.load(t,r),h=Atomics.load(t,u),c=Date.now();const p=()=>{if(this._abortError)return void o(i,this._abortError);const a=Atomics.load(t,r);if(a>=e)return void o(n);const d=Atomics.load(t,u);if(a!==l||d!==h)l=a,h=d,c=Date.now();else if(Date.now()-c>=this.sanityTimeoutMs){const t=new Error(`pipeline threaded barrier stalled at generation ${a} of ${e} for ${this.sanityTimeoutMs}ms`);return this._abort(t),void o(i,t)}if(s){const e=Math.max(1,Math.min(200,this.sanityTimeoutMs)),n=s(t,r,a,e);n.async?n.value.then(p):Promise.resolve().then(p)}else setTimeout(p,1)};p()})}_abort(e){if(!this._abortError&&(this._abortError=e||new Error("pipeline threaded run aborted"),this._lastRunAborted=!0,this.i32&&this._entry&&(Atomics.store(this.i32,this._entry.abortIndex,1),Atomics.notify(this.i32,this._entry.genIndex)),this.pool&&this.pool.workers))for(const e of this.pool.workers)!e.dead&&e.state.pending.size>0&&e.die(this._abortError)}abortRuns(e){this.threaded&&this._abort(e)}_readResults(e){const t=this.f32,r=this.plan.results,s=new Array(this._resultReads.length);for(let r=0;r{const{utils:r}=i(),{Input:n}=s(),{FusionFallback:a}=ct();function o(e){return e&&"function"==typeof e.toArray?e.toArray():e}function u(e,t,r){const s=e.limits,n=Math.min(s.maxStorageBufferBindingSize,s.maxBufferSize);if(t>n)throw new a(`${r} needs ${t} bytes but this device allows ${n} per storage buffer`)}function l(e){const t=e instanceof n?Array.from(e.size):Array.from(r.getDimensions(e));for(;t.length<3;)t.push(1);return t}function h(e,t){switch(e){case"Integer":return"number"==typeof t&&Number.isInteger(t);case"Boolean":return"boolean"==typeof t;default:return"number"==typeof t}}function c(e){return Boolean(e)&&"object"==typeof e&&!(e instanceof n)&&("function"==typeof e.toArray||"function"==typeof e.delete)}t.exports={WebGPUPipelineExecutor:class e{static async compile(t,r,s){for(let e=0;er.getVariableType(e,h)).join(",");let p=s.get(c);if(!p){let e;if(i[a.kernel]){const t=this.pipeline._cloneKernel(u.clone);this._extraShortcuts.push(t),e=t.kernel}else i[a.kernel]=!0,e=u.clone.kernel;await this._prepareKernel(e,l),p={id:s.size,kernel:e},s.set(c,p)}o[n]=p}this._scratch=null;for(let e=0;e{const r=e.output;let s=1;for(let e=0;e{let t=f.get(e);return void 0===t&&(t=f.size,f.set(e,t)),t},g=new Map;this._passes=new Array(t.steps.length);for(let s=0;s{const t=i.argBindings[e.index];return"literal"===t.source?"l"+t.value:"a"+t.index}).join(","),S=null!==f.randomSeedOffset&&null===d.randomSeed,T=c.id+":"+y.map(m).join(",")+">"+m(b)+":"+v+(S?"#"+s:"");let A=g.get(T);if(!A){const e=new ArrayBuffer(f.byteLength),t=new Uint32Array(e),r=new Int32Array(e),s=new Float32Array(e),n=d._computeDispatch(d.threadDim);t[0]=d.threadDim[0],t[1]=d.threadDim[1],t[2]=d.threadDim[2],t[3]=n.dispatchWidth;for(let e=0;e>>0);const u=h.createBuffer({size:f.byteLength,usage:72}),l=o.length>0||S;l||p.writeBuffer(u,0,e);const c=[{binding:0,resource:{buffer:u}}];for(let e=0;e{const r=e.binding;if("step"===r.source){const e=t.steps[r.step],s=this._planBuffers[e.outputBuffer],n=o[r.step].kernel,i=s.cells*n.componentCount*4,a={kind:"step",buffer:s.buffer,offset:y,byteLength:i,output:e.output,componentCount:n.componentCount,kernel:n};return y+=function(e){return 16*Math.ceil(e/16)}(i),a}return"pipelineArg"===r.source?{kind:"arg",index:r.index}:{kind:"literal",value:r.value}}),y>0&&(this._staging=h.createBuffer({size:y,usage:9}))}_representativeArgs(e,t){const r=new Array(e.argBindings.length);for(let s=0;s>>0),s.writeBuffer(r.paramsBuffer,0,r.mirror)}}const i=t.createCommandEncoder();for(let e=0;e{const t=this._staging.getMappedRange(),r=this._shapeResults(e,t);return this._staging.unmap(),r}):Promise.resolve(this._shapeResults(e,null))}_shapeResults(e,t){const r=this.plan.results,s=new Array(this._resultReads.length);for(let r=0;r{const{Input:r}=s(),{utils:n}=i(),a="pipeline intermediate results cannot be read during orchestration",o="a pipeline must return a handle, or an Array or plain object of handles",u="pipeline has been destroyed",l="the orchestration function must be synchronous; async functions and generators cannot be traced",h="this handle belongs to a different trace; handles do not survive re-trace or cross pipelines";var c=class{};let p=null;var d=class{constructor(e){this.gpu=e,this.steps=[],this.kernels=[],this.kernelIndexes=new Map,this.handleMeta=new WeakMap,this.held=[]}createHandle(e){const t=Object.freeze(new c),r=new Proxy(t,{get(e,t){if(t===Symbol.toPrimitive||"valueOf"===t||"toString"===t)return()=>{throw new Error("pipeline intermediate results cannot be used in arithmetic or conditions during orchestration")};throw new Error(a)},set(){throw new Error(a)},ownKeys(){throw new Error(a)},has(){throw new Error(a)},getOwnPropertyDescriptor(){throw new Error(a)}});return this.handleMeta.set(r,e),r}recordKernelCall(e,t){const r=e.kernel;if(r.gpu!==this.gpu)throw new Error("pipelines can only call kernels created by the same GPU instance");if(r.graphical)throw new Error("graphical kernels are not supported inside pipelines");if(r.subKernels&&r.subKernels.length>0)throw new Error("kernel maps are not supported inside pipelines");if(!r.output)throw new Error("kernels called inside a pipeline must have a fixed output size");let s=this.kernelIndexes.get(e);void 0===s&&(s=this.kernels.length,this.kernels.push(e),this.kernelIndexes.set(e,s));const n=new Array(t.length);for(let e=0;ef(e,t)):e}function m(e){for(let t=0;t{if(this.destroyed)throw new Error(u);if(this.plan||(this.plan=this._buildPlan(),this._executor=void 0),void 0===this._executor&&await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;if(this._dropExecutor(),e.recompilable){if(await this._prepareExecutor(t),this._executor)try{return await this._guardAsync(this._executor.execute(t))}catch(e){if(!e||!e.isFusionFallback)throw e;this._dropExecutor(),this._degrade(e.message)}}else this._degrade(e.message)}return this._executeGeneric(this.plan,t,s)}),i=()=>{this._inFlight--,r.length>0&&m(r)};return n.then(i,i),this._tail=n.then(b,b),n}_guardAsync(e){return e&&"function"==typeof e.then?e.then(null,e=>{throw this._dropExecutor(),e}):e}setConstants(e){this.constants=Object.assign({},e||{});const t=()=>{this._releasePlan()};return this._tail=this._tail.then(t,t),this}destroy(){if(this.destroyed=!0,this.gpu&&this.gpu.pipelines){const e=this.gpu.pipelines.indexOf(this);-1!==e&&this.gpu.pipelines.splice(e,1)}this._executor&&"function"==typeof this._executor.abortRuns&&this._executor.abortRuns(new Error(u));const e=()=>{this._releasePlan()},t=this._tail.then(e,e);return this._tail=t,t}_buildPlan(){const e=new d(this.gpu),t=new Array(this.argumentCount);for(let r=0;r({key:r,binding:e.bindValue(t)}))};if(t instanceof c)throw new Error(h);if("object"==typeof t&&!ArrayBuffer.isView(t)){if("function"==typeof t.then)throw new Error(l);const r=Object.getPrototypeOf(t);if(r!==Object.prototype&&null!==r)throw new Error(o);const s=[];for(const r in t)t.hasOwnProperty(r)&&s.push({key:r,binding:e.bindValue(t[r])});if(0===s.length)throw new Error(o);return{kind:"object",entries:s}}throw new Error(o)}(e,s),i=function(e,t){const r=new Array(e.length).fill(-1);for(let t=0;te.binding)),a=e.kernels.map(e=>({shortcut:e,clone:this._cloneKernel(e)}));return{steps:e.steps,buffers:i,results:n,kernels:a,held:e.held,genericClones:new Map}}_genericClone(e,t){const r=t.argBindings.map(e=>"step"===e.source?"T":"pipelineArg"===e.source?"a"+e.index:"l").join(","),s=t.kernel+":"+t.outputBuffer+":"+r;let n=e.genericClones.get(s);return n||(n=this._cloneKernel(e.kernels[t.kernel].clone,{immutable:!1,dynamicArguments:!1}),e.genericClones.set(s,n)),n}_prepareExecutor(e){if(this._fusionDisabled)return void(this._executor=!1);const t=this.plan.kernels;if(t.length>0&&"webgpu"===t[0].clone.kernel.constructor.mode){const{WebGPUPipelineExecutor:t}=pt();return t.compile(this,this.plan,e).then(e=>{this._executor=e,this.executorKind=e.kind,this.fallbackReason=null},e=>{this._degrade(e&&e.message||"fused executor unavailable")})}try{const{WebAssemblyPipelineExecutor:t}=ct();this._executor=t.compile(this,this.plan,e),this.executorKind=this._executor.kind,this.fallbackReason=null}catch(e){this._degrade(e&&e.message||"fused executor unavailable")}}_dropExecutor(){this._executor&&this._executor.destroy(),this._executor=void 0}_degrade(e){this._executor=!1,this.executorKind="generic",this.fallbackReason=e}_cloneKernel(e,t){const r=e.kernel,s=Object.assign({output:Array.from(r.output),pipeline:!0,immutable:!0,dynamicArguments:!0},t||{}),n=["constants","constantTypes","precision","loopMaxIterations","strictIntegers","fixIntegerDivisionAccuracy","optimizeFloatMemory","tactic","functions","nativeFunctions","injectedNative","debug","randomSeed","returnType","loopUnrollLimit","_optimizerDisabled","_inliningDisabled"];r.declaredArgumentTypes&&(s.argumentTypes=r.declaredArgumentTypes.slice());for(let e=0;e1?"function (v) { return v[this.thread.z][this.thread.y][this.thread.x]; }":t[1]>1?"function (v) { return v[this.thread.y][this.thread.x]; }":"function (v) { return v[this.thread.x]; }",a=t[2]>1?[t[0],t[1],t[2]]:t[1]>1?[t[0],t[1]]:[t[0]];n=this.gpu.createKernel(i,{output:a,pipeline:!0,immutable:!1}),e.genericClones.set(s,n)}return n(r)}_genericEagerUploadsPay(e){return 0!==e.kernels.length&&"gpu"===e.kernels[0].clone.kernel.constructor.mode}_eagerUploads(e,t){const s=new Array(t.length).fill(null);for(let n=0;n0?e.kernels[0].clone.kernel.constructor.mode:null,a="gpu"===i||"webgpu"===i,o=s||new Array(t.length).fill(null);if(a&&!s)for(let s=0;s{const{utils:r}=i(),{Input:n}=s(),{getActiveTrace:a}=dt();function o(e,t){if(t.kernel)return void(t.kernel=e);const s=r.allPropertiesOf(e);for(let r=0;rt.kernel[n]),t.__defineSetter__(n,e=>{t.kernel[n]=e})))}t.kernel=e}t.exports={kernelRunShortcut:function(e){function t(t){e.build.apply(e,t),e.checkArgumentTypes(t);let s=e.switchingKernels?void 0:e.run.apply(e,t);for(let n=0;e.switchingKernels;n++){if(n>=4){const t=e.resetSwitchingKernels();throw new Error(`this kernel cannot run the arguments it was given (${r(t)}); it did not settle on a kernel for them after 4 attempts. Create a separate kernel for this call's argument types.`)}const i=e.resetSwitchingKernels(),a=e.onRequestSwitchKernel(i,t,e);p.kernel=e=a,a.checkArgumentTypes(t),s=a.switchingKernels?void 0:a.run.apply(a,t),a.fallbackRequested&&(s=e.run.apply(e,t))}return s}function r(e){return e&&e.length?e.map(e=>"argumentTypeMismatch"===e.type?`argument ${e.index} is now ${e.needed}`:e.type).join(", "):"unknown reason"}function s(r){if(e.onAsyncModeUpgrade){const t=e.onAsyncModeUpgrade;e.onAsyncModeUpgrade=null;const n=l(r);return t(n,e).then(e=>(e&&p.replaceKernel(e),s(n)))}try{if(!0===e.constructor.isAsync)return e.build.apply(e,r),Promise.resolve(e.run.apply(e,r));for(let e=0;es(e));const n=t(r);return e.renderKernels?Promise.resolve(e.renderKernels()):e.renderOutput?e.renderOutputAsync?e.renderOutputAsync():Promise.resolve(e.renderOutput()):Promise.resolve(n)}catch(e){return Promise.reject(e)}}function i(e){return Boolean(e)&&"WebGPUBuffer"===e.type}function u(e){const t=l(e),r=[];for(let e=0;e{t[s]=e}))}return Promise.all(r).then(()=>t)}function l(e){const t=new Array(e.length);for(let r=0;r{try{e(c.apply(this,arguments))}catch(e){t(e)}})},p.replaceKernel=function(t){o(e=t,p)},o(e,p),p}}}),mt=e((e,r)=>{const{gpuMock:s}=t(),{utils:n}=i(),{Kernel:o}=a(),{CPUKernel:u}=d(),{HeadlessGLKernel:l}=Se(),{WebGL2Kernel:h}=rt(),{WebGLKernel:c}=ve(),{WebGPUKernel:p}=at(),{WebAssemblyKernel:f}=ht(),{kernelRunShortcut:m}=ft(),{Pipeline:g}=dt(),y=[l,h,c,f],x=["gpu","cpu"],b={headlessgl:l,webgl2:h,webgl:c,webgpu:p,webasm:f};let v=!0;function S(e){if(!e)return{};const t=Object.assign({},e);return e.hasOwnProperty("floatOutput")&&(n.warnDeprecated("setting","floatOutput","precision"),t.precision=e.floatOutput?"single":"unsigned"),e.hasOwnProperty("outputToTexture")&&(n.warnDeprecated("setting","outputToTexture","pipeline"),t.pipeline=Boolean(e.outputToTexture)),e.hasOwnProperty("outputImmutable")&&(n.warnDeprecated("setting","outputImmutable","immutable"),t.immutable=Boolean(e.outputImmutable)),e.hasOwnProperty("floatTextures")&&(n.warnDeprecated("setting","floatTextures","optimizeFloatMemory"),t.optimizeFloatMemory=Boolean(e.floatTextures)),t}r.exports={GPU:class e{static disableValidation(){v=!1}static enableValidation(){v=!0}static get isGPUSupported(){return y.some(e=>e.isSupported)}static get isKernelMapSupported(){return y.some(e=>e.isSupported&&e.features.kernelMap)}static get isOffscreenCanvasSupported(){return"undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas||"undefined"!=typeof importScripts}static get isWebGLSupported(){return c.isSupported}static get isWebGL2Supported(){return h.isSupported}static get isHeadlessGLSupported(){return l.isSupported}static get isWebGPUSupported(){return p.isSupported}static isWebGPUAvailable(){return p.isSupported?navigator.gpu.requestAdapter().then(e=>null!==e,()=>!1):Promise.resolve(!1)}static get isWebAssemblySupported(){return f.isSupported}static get isCanvasSupported(){return"undefined"!=typeof HTMLCanvasElement}static get isGPUHTMLImageArraySupported(){return h.isSupported}static get isSinglePrecisionSupported(){return y.some(e=>e.isSupported&&e.features.isFloatRead&&e.features.isTextureFloat)}constructor(t){if(t=t||{},this.canvas=t.canvas||null,this.context=t.context||null,this.mode=t.mode,this.Kernel=null,this._webGPUDecision=null,"async"===t.mode&&(p.isSupported?e.isWebGPUAvailable().then(e=>{this._webGPUDecision=e},()=>{this._webGPUDecision=!1}):this._webGPUDecision=!1),this.kernels=[],this.pipelines=[],this.functions=[],this.nativeFunctions=[],this.injectedNative=null,"dev"!==this.mode){if(this.chooseKernel(),t.functions)for(let e=0;er.argumentTypes[e]));const l=this;function h(e){console.warn("Falling back to CPU"+(y.fallbackReason?`: ${y.fallbackReason}`:""));const r=new u(t,{argumentTypes:y.argumentTypes,constantTypes:y.constantTypes,graphical:y.graphical,loopMaxIterations:y.loopMaxIterations,constants:y.constants,dynamicOutput:y.dynamicOutput,dynamicArgument:y.dynamicArguments,output:y.output,precision:y.precision,pipeline:y.pipeline,immutable:y.immutable,optimizeFloatMemory:y.optimizeFloatMemory,fixIntegerDivisionAccuracy:y.fixIntegerDivisionAccuracy,functions:y.functions,nativeFunctions:y.nativeFunctions,injectedNative:y.injectedNative,subKernels:y.subKernels,strictIntegers:y.strictIntegers,_optimizerDisabled:y._optimizerDisabled,loopUnrollLimit:y.loopUnrollLimit,randomSeed:y.randomSeed,debug:y.debug,asyncMode:y.asyncMode,onRequestFallback:h,onRequestSwitchKernel:c,canvas:y.graphical&&!y.context?y.canvas:null});r.fallbackReason=y.fallbackReason,r.build.apply(r,e);const s=r.run.apply(r,e);return y.replaceKernel(r),!l.canvas&&r.canvas&&(l.canvas=r.canvas),!l.context&&r.context&&(l.context=r.context),s}function c(e,r,s){s.debug&&console.warn("Switching kernels");let n=null;if(s.signature&&!a[s.signature]&&(a[s.signature]=s),s.dynamicOutput)for(let t=e.length-1;t>=0;t--){const r=e[t];"outputPrecisionMismatch"===r.type&&(n=r.needed)}const o=s.constructor,u=o.getArgumentTypes(s,r),l=o.getSignature(s,u),p=a[l];if(p)return p.onActivate(s),p;const d=a[l]=new o(t,{argumentTypes:u,constantTypes:s.constantTypes,graphical:s.graphical,loopMaxIterations:s.loopMaxIterations,constants:s.constants,dynamicOutput:s.dynamicOutput,dynamicArgument:s.dynamicArguments,context:s.context,canvas:s.canvas,output:n||s.output,precision:s.precision,pipeline:s.pipeline,immutable:s.immutable,optimizeFloatMemory:s.optimizeFloatMemory,fixIntegerDivisionAccuracy:s.fixIntegerDivisionAccuracy,functions:s.functions,nativeFunctions:s.nativeFunctions,injectedNative:s.injectedNative,subKernels:s.subKernels,strictIntegers:s.strictIntegers,_optimizerDisabled:s._optimizerDisabled,loopUnrollLimit:s.loopUnrollLimit,randomSeed:s.randomSeed,debug:s.debug,asyncMode:s.asyncMode,gpu:s.gpu,validate:v,returnType:s.returnType,tactic:s.tactic,onRequestFallback:h,onRequestSwitchKernel:c,texture:s.texture,mappedTextures:s.mappedTextures,drawBuffersMap:s.drawBuffersMap});return d.build.apply(d,r),y.replaceKernel(d),i.push(d),d}const d=Object.assign({context:this.context,canvas:this.canvas,functions:this.functions,nativeFunctions:this.nativeFunctions,injectedNative:this.injectedNative,gpu:this,validate:v,onRequestFallback:h,onRequestSwitchKernel:c},o);"async"===this.mode&&(d.asyncMode=!0);let f,g=this.Kernel;"async"===this.mode&&o.graphical&&!0===this._webGPUDecision&&(g=p,d.canvas===this.canvas&&(d.canvas=o.canvas||null),d.context===this.context&&(d.context=o.context||null),d.asyncMode=!0);try{f=new g(t,d)}catch(e){if(g===this.Kernel)throw e;f=new this.Kernel(t,Object.assign({},d,{canvas:this.canvas,context:this.context}))}const y=m(f);if("async"===this.mode&&p.isSupported&&!(f instanceof p)){const r=this;f.onAsyncModeUpgrade=function(s,n){return e.isWebGPUAvailable().then(e=>{if(!e)return null;if(n.graphical)return n.debug&&console.warn("webgpu upgrade declined: graphical kernels keep their canvas"),null;let a;try{a=new p(t,{functions:n.functions,nativeFunctions:n.nativeFunctions,injectedNative:n.injectedNative,gpu:r,validate:v,asyncMode:!0,output:n.output,pipeline:n.pipeline,immutable:n.immutable,dynamicOutput:n.dynamicOutput,dynamicArguments:!0,loopMaxIterations:n.loopMaxIterations,constants:n.constants,constantTypes:n.constantTypes,argumentTypes:n.argumentTypes,precision:n.precision,tactic:n.tactic,strictIntegers:n.strictIntegers,_optimizerDisabled:n._optimizerDisabled,loopUnrollLimit:n.loopUnrollLimit,fixIntegerDivisionAccuracy:n.fixIntegerDivisionAccuracy,subKernels:n.subKernels,graphical:n.graphical,debug:n.debug}),a.build.apply(a,s)}catch(e){return n.debug&&console.warn("webgpu upgrade declined: "+e.message),null}return a._buildPromise.then(()=>(i.push(a),a),e=>(n.debug&&console.warn("webgpu upgrade declined: "+e.message),a.destroy(),null))},()=>null)}}return this.canvas||(this.canvas=f.canvas),this.context||(this.context=f.context),i.push(f),y}createPipeline(e,t){if("function"!=typeof e)throw new Error("createPipeline requires an orchestration function");if("dev"===this.mode)throw new Error("createPipeline is not supported in dev mode");const r=new g(this,e,t);this.pipelines.push(r);const s=function(){return r.call(arguments)};return s.pipeline=r,s.setConstants=function(e){return r.setConstants(e),s},s.destroy=function(){return r.destroy()},Object.defineProperty(s,"executorKind",{get:()=>r.executorKind}),Object.defineProperty(s,"fallbackReason",{get:()=>r.fallbackReason}),Object.defineProperty(s,"plan",{get:()=>r.plan}),Object.defineProperty(s,"backend",{get:()=>{const e=r.executorKind;if("fused-sync"===e||"fused-threaded"===e)return"webasm";if("fused-encoder"===e)return"webgpu";const t=r.plan;if(!t)return null;for(const[e,r]of t.genericClones)if(0!==e.indexOf("up:"))return r.kernel.constructor.mode;return t.kernels.length>0?t.kernels[0].clone.kernel.constructor.mode:null}}),s}createKernelMap(){let e,t;const r=typeof arguments[arguments.length-2];if("function"===r||"string"===r?(e=arguments[arguments.length-2],t=arguments[arguments.length-1]):e=arguments[arguments.length-1],!("dev"===this.mode||this.Kernel.isSupported&&this.Kernel.features.kernelMap)){if("webgpu"===this.Kernel.mode)throw new Error("WebGPU backend does not yet support createKernelMap");if(this.mode&&x.indexOf(this.mode)<0&&"webasm"!==this.Kernel.mode)throw new Error(`kernelMap not supported on ${this.Kernel.name}`)}const s=S(t);if(t&&"object"==typeof t.argumentTypes&&(s.argumentTypes=Object.keys(t.argumentTypes).map(e=>t.argumentTypes[e])),Array.isArray(arguments[0])){s.subKernels=[];const e=arguments[0];for(let t=0;t0)throw new Error('Cannot call "addNativeFunction" after "createKernels" has been called.');return this.nativeFunctions.push(Object.assign({name:e,source:t},r)),this}injectNative(e){return this.injectedNative=e,this}destroy(){return new Promise((e,t)=>{this.kernels||e(),setTimeout(()=>{try{let r=Promise.resolve();if(this.pipelines){const e=this.pipelines.slice();r=Promise.all(e.map(e=>Promise.resolve(e.destroy()).catch(()=>{})))}const s=()=>{try{const e=this.kernels.slice();for(let t=0;t{const{utils:r}=i();t.exports={alias:function(e,t){const s=t.toString();return new Function(`return function ${e} (${r.getArgumentNamesFromString(s).join(", ")}) {\n ${r.getFunctionBodyFromString(s)}\n}`)()}}}),yt=e((e,t)=>{const{GPU:r}=mt(),{alias:o}=gt(),{utils:p}=i(),{Input:f,input:m}=s(),{Texture:g}=n(),{FunctionBuilder:y}=u(),{FunctionNode:x}=h(),{CPUFunctionNode:b}=c(),{CPUKernel:v}=d(),{HeadlessGLKernel:S}=Se(),{WebGLFunctionNode:T}=M(),{WebGLKernel:A}=ve(),{kernelValueMaps:w}=be(),{WebGL2FunctionNode:_}=Te(),{WebGL2Kernel:E}=rt(),{kernelValueMaps:I}=tt(),{WGSLFunctionNode:k}=st(),{WebGPUKernel:C}=at(),{WebGPUContext:L}=nt(),{WebGPUBufferResult:D}=it(),{WebAssemblyFunctionNode:F}=ut(),{WebAssemblyKernel:$}=ht(),{GLKernel:R}=N(),{Kernel:G}=a(),{FunctionTracer:V}=l();t.exports={alias:o,CPUFunctionNode:b,CPUKernel:v,GPU:r,FunctionBuilder:y,FunctionNode:x,HeadlessGLKernel:S,Input:f,input:m,Texture:g,utils:p,WebGL2FunctionNode:_,WebGL2Kernel:E,webGL2KernelValueMaps:I,WebGLFunctionNode:T,WebGLKernel:A,webGLKernelValueMaps:w,WGSLFunctionNode:k,WebGPUKernel:C,WebGPUContext:L,WebGPUBufferResult:D,WebAssemblyFunctionNode:F,WebAssemblyKernel:$,GLKernel:R,Kernel:G,FunctionTracer:V,plugins:{mathRandom:O()}}});return e((e,t)=>{const r=yt(),s=r.GPU;for(const e in r)r.hasOwnProperty(e)&&"GPU"!==e&&(s[e]=r[e]);function n(e){e.GPU&&e.GPU.prototype&&e.GPU.prototype.createKernel||Object.defineProperty(e,"GPU",{configurable:!0,get:()=>s,set(){}})}s.GPU=s,"undefined"!=typeof window&&n(window),"undefined"!=typeof self&&n(self),t.exports=s})()}); \ No newline at end of file diff --git a/docs/design/compiler-optimizations.md b/docs/design/compiler-optimizations.md new file mode 100644 index 00000000..fcafde38 --- /dev/null +++ b/docs/design/compiler-optimizations.md @@ -0,0 +1,151 @@ +# Compiler optimizations — design contract + +Approved. Every decision below is settled; agents build to this, and any +deviation needs a named reason in the final report. + +## Scope + +Every tier that EMITS code gets every transform APPLICABLE to it. `dev` is +untouched — it executes the user's actual function through gpu-mock, so there +is no emission to optimize. + +| transform | cpu | webasm | webgl/webgl2/headlessgl | webgpu | +|---|---|---|---|---| +| **H** loop-invariant hoisting of pure reads | yes | yes | yes | yes | +| **T1** thread/coordinate localization | yes | n/a | n/a | n/a | +| **T2** helper inlining (internal + user) | yes | yes | yes | yes | +| **T3** tiny literal-loop unrolling | yes | yes | yes | yes | + +T1 is the only exclusion and it is a fact, not a judgment: wasm keeps thread +ids in mutable globals, GLSL/WGSL in locals/builtins. There is nothing to +localize. On cpu they are properties of a shared mutable object (`_this.thread.x` +per access) and become loop locals. + +Measured on a desktop (1M cells, median of 7, identical math both sides; +`scratchpad/xform-value.mjs`): + +| transform | cpu | webasm | GL (headless-gl, desktop) | +|---|---|---|---| +| T2 helper in hot loop -> inlined | 1.05x | **2.76x** | 1.17x | +| T3 literal 4-trip loop -> unrolled | **3.27x** | 1.88x | 1.02x | + +webasm's T2 number is not call overhead: the SIMD emitter lane-scalarizes +helper calls (thread state and PCG state swap per lane around the call), so a +helper in a hot loop turns a vectorized kernel into four scalar calls per quad. +Inlining RESTORES vectorization. The GL numbers are one desktop driver and do +not generalize — mobile shader compilers are much weaker, which is what the +BrowserStack fleet is for. + +## Architecture + +`src/backend/optimizer.js` — a backend-agnostic AST pass at the FunctionBuilder +stage, consumed by every function-node subclass. + +ORDERING IS LOAD-BEARING: + +1. De-minification (existing, base FunctionNode) runs FIRST — the optimizer + must never see comma-folded expressions or statement-position sequences. +2. Optimizer: **H -> T2 -> T3** (T3 after T2 so inlined loops qualify; H before + both so hoisted temps are visible to them). +3. GL's `normalizeBlock` / loop normalization / do-while rotation runs LAST — + unrolling may delete loops it would otherwise rewrite, and the #300 hoisting + machinery must see final shapes. +4. On webasm the optimizer runs BEFORE variance analysis and SIMD emission — + that is the entire point, so inlined helper bodies vectorize instead of + forcing lane-scalarized calls. + +## Correctness invariants + +- **Bit-identical to `_optimizerDisabled` output, per backend, on that + backend's own arithmetic** (cpu f64, webasm/GL/WGSL f32). NOT cross-backend; + those differ by design. +- **Seeded `Math.random` streams preserved exactly.** Sharpest edge: webasm's + per-cell and per-lane PCG state. A helper that draws random must inline to an + identical draw sequence. This is a named test case, not an afterthought. +- No FP reassociation. No CSE across float operations. +- **H is restricted to PURE reads** — array element reads whose subscript is + loop-invariant, and constants. Legal precisely because a kernel cannot write + its array arguments. A read whose subscript varies, or any expression with a + call in it, does not hoist. +- Inlined parameters bind as fresh declarations preserving evaluation order + (one binding per argument, evaluated once, in source order). Helper locals + rename outside the `user_` namespace (`cellShadow_` precedent). +- **Per-site best effort**: anything unprovable skips THAT SITE, never the + tier. Un-transformed emission is always valid. + +## Control and failure + +- `kernel._optimizerDisabled` — internal hook (the `_fusionDisabled` + precedent). No public setting. +- `loopUnrollLimit` — public setting, default 8, `0` disables T3. A threshold, + and the knob a user tunes when shader size matters. +- A synchronous BUILD-TIME throw from the optimizer is caught: rebuild with the + optimizer disabled, warn loudly, set `fallbackReason` (#868 contract). + Runtime throws are never caught — they are the user's bug or ours, and + masking them helps nobody. + +## Transform detail + +**H — loop-invariant hoisting.** Within a loop body, an array read whose object +and subscript are both loop-invariant (no dependence on the induction variable +or on anything assigned in the body) hoists to a fresh const before the loop. +Bails on: any assignment to the array name in scope, subscripts containing +calls, loops whose body assigns the object. + +**T1 — coordinate localization (cpu).** `this.thread.x/y/z` reads become the +generated cell loop's own locals. `this.constants.*` and `this.output.*` are +already hoisted; verify and extend where they are not. + +**T2 — helper inlining.** Leaf-first over the FunctionBuilder call graph; +recursion bails (leave the call). Statement-position calls inline as blocks; +expression-position calls hoist to temps using the EXISTING linearization +machinery from the de-minification work. Multi-return helpers use the labeled +block + result temp idiom (`kernelBody:` precedent). Internal emitted helpers +(`divWithIntCheck` under `fixIntegerDivisionAccuracy`, and whatever the phase-0 +audit finds) inline or specialize the same way. An emitted-size budget guards +against megafunctions (V8 deopt on cpu, shader compile time on mobile GL). + +**T3 — tiny-loop unrolling.** Criteria: literal init/test/update, trip count +<= `loopUnrollLimit`, no `break`/`continue`, induction variable never assigned +in the body. Clone the body per iteration substituting the induction variable +as a literal; stamp fresh synthetic positions (`stampSyntheticNodes` +precedent). Unrolled loops shed the LOOP_MAX safe-wrapping entirely. + +## Verification bar + +- **Parity harness, per backend**: spec shapes x sub-kernels x strictIntegers x + fixIntegerDivisionAccuracy x seeded random x the #865/#867 control-flow + shapes, optimized vs `_optimizerDisabled`, compared through Int32 views. + Zero tolerance. webgpu parity runs in the headed browser. +- **Discriminating emission tests both directions**, mutation-checked with cp + backups (never `git checkout`): optimized emission contains no helper call + site and no `for` for a literal 3-trip loop; disabled emission contains both. +- Edge list each transform must pass or provably skip: helper-calls-helper + depth, parameter reassignment inside a helper, array argument aliasing, name + shadowing, early returns, recursion, `Math.random` inside a helper, the #865 + argument shadows, `Input` arguments, dynamic output/arguments. +- Full gates: `npm test`, headed browser suite, SwiftShader failure-set diff + against the 131-entry baseline, and **BrowserStack on real devices** — the + only honest answer to the mobile-GL question. + +## Benchmarks — SELF-CONTAINED + +`scripts/benchmark-optimizer.mjs` in the house style +(`scripts/benchmark-webasm.mjs` is the model): optimized vs `_optimizerDisabled` +across cpu / webasm / headlessgl, on workloads that live IN THE SCRIPT — +helper-heavy, tiny-loop-heavy, stencil, and a control with neither. Cross-check +results before timing. Do NOT touch or depend on the gpu.rocks gauntlet; that +suite's maintainer verifies independently. + +Phase 1 must also SEPARATE H from T3's measured cpu 3.27x: the hand-unrolled +probe that produced it also hoisted an array read, so the attribution between +the two transforms is still unknown. + +## Files + +- `src/backend/optimizer.js` — the pass. +- `src/backend/function-node.js` — invocation point + `_optimizerDisabled`. +- per-backend function nodes — ordering hookups only. +- `scripts/benchmark-optimizer.mjs` +- `test/features/optimizer/*.js` +- README section + `src/index.d.ts` (`loopUnrollLimit`). diff --git a/scripts/benchmark-optimizer.mjs b/scripts/benchmark-optimizer.mjs new file mode 100644 index 00000000..0f301e05 --- /dev/null +++ b/scripts/benchmark-optimizer.mjs @@ -0,0 +1,476 @@ +#!/usr/bin/env node +// Prices the compiler optimizations: the same kernel built normally and with +// `_optimizerDisabled`, on cpu, webasm and headlessgl, in plain Node. Prints +// a GitHub-markdown table plus raw JSON to stdout. +// +// node scripts/benchmark-optimizer.mjs +// node scripts/benchmark-optimizer.mjs --attribution # H-vs-T3 split only +// +// Methodology (matches scripts/benchmark-webasm.mjs): +// - the workloads live IN THIS FILE. Nothing here reaches for an external +// suite, so the numbers are reproducible from a checkout alone +// - every workload is cross-checked optimized-against-disabled BEFORE any +// timing; a mismatch beyond one f32 ULP aborts the run +// - timed runs ping-pong between two input sets so no cache can elide work +// - median of >= 7 runs, warmup excluded +// - each workload is built three ways -- optimizer off, `loopUnrollLimit: 0`, +// and everything on -- so the shipped total splits into what the unroller +// contributes and what the rest do. All three are built and warmed before +// any is timed, and the timed rounds interleave +// - each workload runs in a process of its own, so one workload's V8 state +// cannot decide another's answer +// +// The attribution block answers the one question the design contract left +// open: the hand-written probe that measured T3's 3.27x on cpu ALSO hoisted +// an array read out of the loop, so the split between hoisting and unrolling +// was unknown. It times the same shape in three forms -- the loop as written, +// the loop with the read hoisted BY HAND, and the fully hand-unrolled body -- +// so the two transforms can be priced separately. + +import { createRequire } from 'node:module'; +import { execFileSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +const require = createRequire(import.meta.url); +const { GPU } = require('../src'); + +const scriptPath = fileURLToPath(import.meta.url); +const MEDIAN_RUNS = 7; + +function median(times) { + const sorted = [...times].sort((a, b) => a - b); + return sorted[Math.floor(sorted.length / 2)]; +} + +/** + * The worst relative disagreement between two results, walked in place. + * Copying a million cells into a plain array first -- which is what the + * obvious flatten-then-compare does -- allocates 8MB per build and moves the + * numbers it is supposed to be checking: the coordinate-heavy workload read + * 1.06x that way and 1.82x without, reproducibly. A cross-check has to be + * free, so this one allocates nothing. + */ +function relativeError(a, b) { + if (typeof a === 'number') { + // scale floored at 1: these workloads sum terms that cancel, and a + // relative error against a near-zero total measures the cancellation, + // not the disagreement + return Math.abs(a - b) / Math.max(Math.abs(a), Math.abs(b), 1); + } + let worst = 0; + for (let i = 0; i < a.length; i++) { + const error = relativeError(a[i], b[i]); + if (error > worst) worst = error; + } + return worst; +} + +// a shader compiler is free to reassociate, so semantically identical GLSL can +// land one f32 ULP apart; anything past a few of those is a real disagreement +const CROSS_CHECK_TOLERANCE = 1e-6; + +const N = 1 << 20; +function makeVector(seed) { + const v = new Float32Array(N); + for (let i = 0; i < N; i++) v[i] = ((i * 13 + seed) % 1000) / 500 - 1; + return v; +} + +const SIZE = 256; +function makeMatrix(seed) { + const m = []; + for (let y = 0; y < SIZE; y++) { + const row = new Float32Array(SIZE); + for (let x = 0; x < SIZE; x++) row[x] = ((x * 31 + y * 17 + seed) % 100) / 100; + m.push(row); + } + return m; +} + +function poly(x) { + return x * x * 0.5 + x * 0.25 - 0.125; +} + +function scale(x, by) { + return poly(x) * by; +} + +function outer(x) { + return scale(x, 2) + 1; +} + +function clampish(x) { + if (x < 0) return 0; + return x * x * 0.25; +} + +const WORKLOADS = [ + { + // H's home ground: a read whose subscript never changes, inside a loop + name: 'hoistable read, 8-trip loop, 1M cells', + source: function (a) { + let s = 0; + for (let i = 0; i < 8; i++) s += a[this.thread.x] * (i + 1); + return s; + }, + output: [N], + inputs: [[makeVector(1)], [makeVector(2)]], + }, + { + // a stencil reads its neighbourhood; the CENTRE is invariant to the + // sweep, the neighbours are not + name: 'stencil 3x3, 256x256', + source: function (a) { + let s = 0; + for (let dy = -1; dy <= 1; dy++) { + for (let dx = -1; dx <= 1; dx++) { + const y = Math.min(Math.max(this.thread.y + dy, 0), 255); + const x = Math.min(Math.max(this.thread.x + dx, 0), 255); + s += a[y][x] * 0.5 + a[this.thread.y][this.thread.x] * 0.125; + } + } + return s / 9; + }, + output: [SIZE, SIZE], + inputs: [[makeMatrix(1)], [makeMatrix(2)]], + }, + { + // T2's shape, and the one the design contract priced at 2.76x on webasm: + // a helper called from inside a hot loop. The SIMD emitter has no vector + // form for a call, so every iteration lane-scalarizes into four scalar + // calls with thread and PCG state swapped around each; inlining is what + // gives the loop back to the vectorizer + name: 'helper in a hot loop, 1M cells', + source: function (a) { + let s = 0; + for (let i = 0; i < 8; i++) s += poly(a[this.thread.x] + i * 0.01); + return s; + }, + settings: { functions: [poly] }, + output: [N], + inputs: [[makeVector(3)], [makeVector(4)]], + }, + { + // T2 through depth: three helpers deep, expanded leaf-first + name: 'helper chain 3 deep, 1M cells', + source: function (a) { + return outer(a[this.thread.x]); + }, + settings: { functions: [poly, scale, outer] }, + output: [N], + inputs: [[makeVector(13)], [makeVector(14)]], + }, + { + // a helper with an early return: folded to a conditional rather than left + // as a call, which is the shape most likely to cost more than it saves + name: 'branching helper per cell, 1M cells', + source: function (a) { + return clampish(a[this.thread.x]) + clampish(a[this.thread.x] * 2); + }, + settings: { functions: [clampish] }, + output: [N], + inputs: [[makeVector(15)], [makeVector(16)]], + }, + { + // T3's shape: a literal loop small enough to unroll whole + name: 'literal 4-trip loop, 1M cells', + source: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return s; + }, + output: [N], + inputs: [[makeVector(5)], [makeVector(6)]], + }, + { + // T3 at its best: literal bounds nested two deep, so the whole 3x3 sweep + // becomes nine copies with no counters left + name: 'nested literal 3x3 loop, 256x256', + source: function (a) { + let s = 0; + for (let dy = 0; dy < 3; dy++) { + for (let dx = 0; dx < 3; dx++) { + s += a[this.thread.y][this.thread.x] * (dy * 3 + dx); + } + } + return s; + }, + output: [SIZE, SIZE], + inputs: [[makeMatrix(9)], [makeMatrix(10)]], + }, + { + // T1's home ground: no loop to hoist out of or unroll, just coordinates + // read over and over. On cpu each read is a property lookup on a shared + // mutable object; every other backend already holds them in something + // local, so this doubles as their control + name: 'coordinate-heavy straight-line map, 1M cells', + source: function (a) { + const x = this.thread.x; + const y = this.thread.y; + const z = this.thread.z; + return a[x] * 0.5 + x * 0.25 + y + z + + (x + y) * (x - z) * 1e-9 + a[this.thread.x] * this.thread.x * 1e-9; + }, + output: [N], + inputs: [[makeVector(11)], [makeVector(12)]], + }, + { + // the control: no loop for H to hoist out of, no helper to inline, no + // literal loop to unroll, one coordinate read. Any movement here is + // noise, and says how much of the rest is signal + name: 'control: straight-line map, 1M cells', + source: function (a) { + const x = a[this.thread.x]; + return x * x * 0.5 + Math.sqrt(Math.abs(x)) - x * 0.25; + }, + output: [N], + inputs: [[makeVector(7)], [makeVector(8)]], + }, +]; + +// The four builds each workload is priced at, each turning one more transform +// on: nothing, then H and T1, then T2, then T3. `loopUnrollLimit: 0` is the +// public switch; `_inliningDisabled` is the internal one T2 needed, for the +// same reason `_optimizerDisabled` exists -- a per-transform number cannot be +// read off a build that has more than one transform in it. H and T1 still +// share a column because neither has a switch of its own; on the loop +// workloads that column is H, and on the coordinate-heavy one -- which has no +// loop to hoist out of -- it is T1. +const BUILDS = { + disabled: { _optimizerDisabled: true }, + noInline: { _inliningDisabled: true, loopUnrollLimit: 0 }, + noUnroll: { loopUnrollLimit: 0 }, + optimized: {}, +}; + +function buildKernel(mode, workload, build, gpus) { + const gpu = new GPU({ mode }); + gpus.push(gpu); + return gpu.createKernel(workload.source, Object.assign({ + output: workload.output, + loopMaxIterations: workload.loopMaxIterations || 1000, + }, workload.settings || {}, BUILDS[build])); +} + +/** + * Every build is constructed and warmed before any of them is timed, and the + * timed rounds interleave. Timing them one after another instead moved the + * answer by 30%: each is a separate emitted function, and whichever one V8 + * meets first pays for the tier-up. + */ +function measure(mode, workload) { + const gpus = []; + const names = Object.keys(BUILDS); + try { + const kernels = {}; + const samples = {}; + let reference = null; + let error = 0; + for (const name of names) { + const kernel = buildKernel(mode, workload, name, gpus); + const result = kernel.apply(null, workload.inputs[0]); + if (reference === null) { + reference = result; + } else { + error = Math.max(error, relativeError(reference, result)); + if (!(error <= CROSS_CHECK_TOLERANCE)) { + throw new Error(`RESULT MISMATCH in ${ workload.name } (${ mode }/${ name }): relative error ${ error }`); + } + } + for (let i = 0; i < 4; i++) kernel.apply(null, workload.inputs[i % 2]); + kernels[name] = kernel; + samples[name] = []; + } + const runs = mode === 'cpu' ? MEDIAN_RUNS : MEDIAN_RUNS + 4; + for (let round = 0; round < runs; round++) { + const inputs = workload.inputs[round % 2]; + for (const name of names) { + const start = process.hrtime.bigint(); + kernels[name].apply(null, inputs); + samples[name].push(Number(process.hrtime.bigint() - start) / 1e6); + } + } + const result = { error }; + for (const name of names) result[name] = +median(samples[name]).toFixed(2); + return result; + } finally { + for (const gpu of gpus) gpu.destroy(); + } +} + +// -------------------------------------------------------------- attribution + +// The design contract's T3 probe, in four forms. `loop` is what a user writes; +// `hoisted` is what H alone produces, written by hand; `unrolled` is what H +// followed by T3 produces, also by hand; `passed` is the same `loop` source +// with the optimizer actually on, so what the pass DOES can be read against +// what the transform is WORTH. loop/hoisted prices H, hoisted/unrolled prices +// T3, loop/unrolled reproduces the contract's combined figure. +// +// Every form is built AND warmed before any of them is timed, and the timed +// rounds interleave. Timing them one after another instead moved the answer +// by 30%: each form is a separate emitted function, and whichever one V8 +// meets first pays for the tier-up. +const ATTRIBUTION = { + name: 'literal 4-trip loop over one invariant read', + forms: { + loop: [function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return s; + }, true], + hoisted: [function (a) { + const x = a[this.thread.x]; + let s = 0; + for (let i = 0; i < 4; i++) s += x * (i + 1); + return s; + }, true], + unrolled: [function (a) { + const x = a[this.thread.x]; + return x * 1 + x * 2 + x * 3 + x * 4; + }, true], + passed: [function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return s; + }, false], + }, + output: [N], + inputs: [[makeVector(9)], [makeVector(10)]], +}; + +function measureAttribution(mode) { + const gpus = []; + try { + const names = Object.keys(ATTRIBUTION.forms); + const kernels = {}; + const samples = {}; + let reference = null; + for (const name of names) { + const [source, disabled] = ATTRIBUTION.forms[name]; + const gpu = new GPU({ mode }); + gpus.push(gpu); + const kernel = gpu.createKernel(source, { + output: ATTRIBUTION.output, + _optimizerDisabled: disabled, + }); + const result = kernel.apply(null, ATTRIBUTION.inputs[0]); + if (reference === null) { + reference = result; + } else { + const error = relativeError(reference, result); + if (!(error <= CROSS_CHECK_TOLERANCE)) { + throw new Error(`ATTRIBUTION MISMATCH (${ mode }/${ name }): relative error ${ error }`); + } + } + // warm every form before timing any of them + for (let i = 0; i < 4; i++) kernel.apply(null, ATTRIBUTION.inputs[i % 2]); + kernels[name] = kernel; + samples[name] = []; + } + for (let round = 0; round < MEDIAN_RUNS + 4; round++) { + const inputs = ATTRIBUTION.inputs[round % 2]; + for (const name of names) { + const start = process.hrtime.bigint(); + kernels[name].apply(null, inputs); + samples[name].push(Number(process.hrtime.bigint() - start) / 1e6); + } + } + const times = {}; + for (const name of names) times[name] = +median(samples[name]).toFixed(2); + return times; + } finally { + for (const gpu of gpus) gpu.destroy(); + } +} + +// --------------------------------------------------------------------- main + +const MODES = [ + ['cpu', () => true], + ['headlessgl', () => GPU.isHeadlessGLSupported], + ['webasm', () => GPU.isWebAssemblySupported], +]; + +// Each workload is measured in a process of its own. Interleaving the three +// builds is enough to keep them honest against each other WITHIN a workload, +// but not across workloads: running the coordinate-heavy shape after six +// others once had V8 hand its un-optimized build a 2x tier-up the other two +// did not get, which read as the transform costing 11% when it is worth 1.8x +// measured alone. A fresh process per workload is what makes the table +// reproducible rather than order-dependent. +function measureWorkloadInChild(index) { + const output = execFileSync(process.execPath, [scriptPath, `--workload=${ index }`], { + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'inherit'], + }); + return JSON.parse(output); +} + +function main() { + const attributionOnly = process.argv.includes('--attribution'); + const modes = MODES.filter(([, supported]) => supported()).map(([mode]) => mode); + const report = { optimizer: [], attribution: {} }; + + const child = process.argv.find(argument => argument.startsWith('--workload=')); + if (child) { + const workload = WORKLOADS[Number(child.split('=')[1])]; + const row = { name: workload.name, modes: {} }; + for (const mode of modes) row.modes[mode] = measure(mode, workload); + process.stdout.write(JSON.stringify(row)); + return; + } + + if (!attributionOnly) { + for (let i = 0; i < WORKLOADS.length; i++) { + const row = measureWorkloadInChild(i); + for (const mode of modes) { + const result = row.modes[mode]; + process.stderr.write( + `${ row.name } / ${ mode }: off ${ result.disabled } ms, ` + + `+H/T1 ${ result.noInline } ms, +T2 ${ result.noUnroll } ms, ` + + `+T3 ${ result.optimized } ms ` + + `(${ (result.disabled / result.optimized).toFixed(2) }x total)\n`); + } + report.optimizer.push(row); + } + + // Each ratio prices exactly one transform, against the build with every + // earlier transform already on. + for (const mode of modes) { + console.log(`\n### ${ mode }`); + console.log('\n| Workload | off | +H/T1 | +T2 | +T3 | H+T1 | T2 | T3 | total |'); + console.log('|---|---|---|---|---|---|---|---|---|'); + for (const row of report.optimizer) { + const r = row.modes[mode]; + console.log( + `| ${ row.name } | ${ r.disabled } ms | ${ r.noInline } ms | ${ r.noUnroll } ms | ` + + `${ r.optimized } ms | ${ (r.disabled / r.noInline).toFixed(2) }× | ` + + `${ (r.noInline / r.noUnroll).toFixed(2) }× | ${ (r.noUnroll / r.optimized).toFixed(2) }× | ` + + `${ (r.disabled / r.optimized).toFixed(2) }× |`); + } + } + } + + for (const mode of modes) { + report.attribution[mode] = measureAttribution(mode); + } + console.log(`\n### H vs T3 attribution — ${ ATTRIBUTION.name }`); + console.log('\n| Mode | as written | hand-hoisted | hand-unrolled | H alone | T3 on top of H | both | pass as shipped |'); + console.log('|---|---|---|---|---|---|---|---|'); + for (const mode of modes) { + const t = report.attribution[mode]; + console.log( + `| ${ mode } | ${ t.loop } ms | ${ t.hoisted } ms | ${ t.unrolled } ms | ` + + `${ (t.loop / t.hoisted).toFixed(2) }× | ${ (t.hoisted / t.unrolled).toFixed(2) }× | ` + + `${ (t.loop / t.unrolled).toFixed(2) }× | ${ (t.loop / t.passed).toFixed(2) }× |`); + } + + console.log('\n' + JSON.stringify(report, null, 2)); +} + +try { + main(); +} catch (error) { + console.error(error); + process.exit(1); +} diff --git a/src/backend/cpu/function-node.js b/src/backend/cpu/function-node.js index 936eb9a9..4e1bb920 100644 --- a/src/backend/cpu/function-node.js +++ b/src/backend/cpu/function-node.js @@ -1,4 +1,5 @@ const { FunctionNode } = require('../function-node'); +const { threadLocalName } = require('../optimizer'); /** * @desc [INTERNAL] Represents a single function, inside JS @@ -6,6 +7,14 @@ const { FunctionNode } = require('../function-node'); *

This handles all the raw state, converted state, etc. Of a single function.

*/ class CPUFunctionNode extends FunctionNode { + /** + * The emitted body is plain JavaScript over real arrays, so `a[y][x]` past + * the end of `a` throws rather than reading a clamped texel. + */ + get readsCanFault() { + return true; + } + /** * @desc Parses the abstract syntax tree for to its *named function* * @param {Object} ast - the AST object to parse @@ -484,9 +493,14 @@ class CPUFunctionNode extends FunctionNode { origin } = this.getMemberExpressionDetails(mNode); switch (signature) { - case 'this.thread.value': - retArr.push(`_this.thread.${ name }`); + case 'this.thread.value': { + // T1: inside the generated cell loop the coordinate IS the loop's own + // counter, so the root body names it instead of re-reading a property + // off the shared thread object + const local = threadLocalName(this, name); + retArr.push(local === null ? `_this.thread.${ name }` : local); return retArr; + } case 'this.output.value': switch (name) { case 'x': diff --git a/src/backend/cpu/kernel.js b/src/backend/cpu/kernel.js index 5610457b..b8c0e40c 100644 --- a/src/backend/cpu/kernel.js +++ b/src/backend/cpu/kernel.js @@ -49,6 +49,16 @@ class CPUKernel extends Kernel { constructor(source, settings) { super(source, settings); + // set BEFORE mergeSettings so an explicit setting still wins. + // Helper inlining (T2) is OFF here, and only here. The emitted body is + // JavaScript, so V8 already inlines small helpers -- doing it ourselves + // measured a consistent net loss across the benchmark suite (0.78-1.02x, + // mean ~0.93) while it is worth 3.7-4.0x on webasm, where a helper call + // forces the SIMD emitter to scalarize per lane. The other transforms + // (hoisting, unrolling, coordinate localization) stay on and carry the + // cpu gains. Tests that exercise the inliner's mechanics through cpu + // emission set this back to false. + this._inliningDisabled = true; this.mergeSettings(source.settings || settings); this._imageData = null; @@ -149,7 +159,7 @@ class CPUKernel extends Kernel { this.setupConstants(); this.setupArguments(arguments); this.validateSettings(arguments); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); if (this.graphical) { const { diff --git a/src/backend/function-builder.js b/src/backend/function-builder.js index 359286f0..f2d4164f 100644 --- a/src/backend/function-builder.js +++ b/src/backend/function-builder.js @@ -1,3 +1,5 @@ +const { buildInlinePlan } = require('./optimizer'); + /** * @desc This handles all the raw state, converted state, etc. of a single function. * [INTERNAL] A collection of functionNodes. @@ -35,8 +37,16 @@ class FunctionBuilder { followingReturnStatement, dynamicArguments, dynamicOutput, + loopUnrollLimit, + localizeThreadCoordinates, } = kernel; + // the internal hook is read once here and handed to every function node, + // so a kernel that rebuilds with optimizations off gets a builder whose + // whole call graph agrees (the `_fusionDisabled` precedent) + const optimizerDisabled = Boolean(kernel._optimizerDisabled); + const inliningDisabled = Boolean(kernel._inliningDisabled); + const argumentTypes = new Array(kernelArguments.length); const constantTypes = {}; @@ -85,6 +95,10 @@ class FunctionBuilder { functionBuilder.trackFunctionCall(functionName, calleeFunctionName, args); }; + const lookupInlineTarget = inliningDisabled ? null : (functionName) => { + return functionBuilder.lookupInlineTarget(functionName); + }; + const onNestedFunction = (ast, source) => { const argumentNames = []; for (let i = 0; i < ast.params.length; i++) { @@ -132,6 +146,10 @@ class FunctionBuilder { plugins, dynamicArguments, dynamicOutput, + optimizerDisabled, + loopUnrollLimit, + localizeThreadCoordinates, + lookupInlineTarget, }, extraNodeOptions || {}); const rootNodeOptions = Object.assign({}, nodeOptions, { @@ -157,6 +175,12 @@ class FunctionBuilder { name: fn.name || undefined, returnType: fn.returnType, argumentTypes: fn.argumentTypes, + // types the USER declared through addFunction, distinct from types a + // build inferred: the emitter applies them as coercions at the call + // boundary, which inlining would delete (#1 of the build review) + hasDeclaredTypes: Boolean(fn.returnType) || (Array.isArray(fn.argumentTypes) ? + fn.argumentTypes.some(type => Boolean(type)) : + Boolean(fn.argumentTypes && Object.keys(fn.argumentTypes).length > 0)), output, plugins, constants, @@ -174,6 +198,10 @@ class FunctionBuilder { triggerImplyArgumentBitRatio, onFunctionCall, onNestedFunction, + optimizerDisabled, + loopUnrollLimit, + localizeThreadCoordinates, + lookupInlineTarget, })); } @@ -216,6 +244,7 @@ class FunctionBuilder { this.lookupChain = []; this.functionNodeDependencies = {}; this.functionCalls = {}; + this._inlinePlan = null; if (this.rootNode) { this.functionMap['kernel'] = this.rootNode; @@ -241,6 +270,24 @@ class FunctionBuilder { } } + /** + * @desc T2's view of the call graph. The whole graph is decided ONCE, before + * any function node is optimized, because inlining is all-or-nothing per + * helper: a helper left with some call sites and not others has its + * parameter types fixed by whichever site the emitter reaches first, and + * dropping a site can change which one that is. Deciding globally keeps the + * optimized build's surviving calls identical to the un-optimized build's. + * @param {String} functionName + * @returns {Object|null} the plan entry, or null when this name must keep + * its call sites + */ + lookupInlineTarget(functionName) { + if (!this._inlinePlan) { + this._inlinePlan = buildInlinePlan(this); + } + return this._inlinePlan.get(functionName) || null; + } + /** * @desc Add the function node directly * diff --git a/src/backend/function-node.js b/src/backend/function-node.js index d3635cc4..6f468c64 100644 --- a/src/backend/function-node.js +++ b/src/backend/function-node.js @@ -1,6 +1,7 @@ const acorn = require('acorn'); const { utils } = require('../utils'); const { FunctionTracer } = require('./function-tracer'); +const { optimize } = require('./optimizer'); const mathProperties = [ 'E', @@ -129,6 +130,21 @@ class FunctionNode { this.dynamicArguments = null; this.strictTypingChecking = false; this.fixIntegerDivisionAccuracy = null; + this.optimizerDisabled = false; + this.loopUnrollLimit = 8; + this.lookupInlineTarget = null; + /** + * Types the USER declared through addFunction (distinct from types a + * build inferred). The emitter applies them as coercions at the call + * boundary, so such a helper must keep its call rather than inline. + */ + this.hasDeclaredTypes = false; + /** + * T1 (thread-coordinate localization) is off by default: measured a net + * loss at scale on the cpu backend. Kept switchable for the emission + * tests and for a future implementation that binds the counters once. + */ + this.localizeThreadCoordinates = false; if (settings) { for (const p in settings) { @@ -141,6 +157,7 @@ class FunctionNode { this.literalTypes = {}; this.validate(); + this._rawAST = null; this._string = null; this._internalVariableNames = {}; } @@ -266,14 +283,46 @@ class FunctionNode { return false; } - getJsAST(inParser) { - if (this.ast) { - return this.ast; + /** + * Whether an out-of-range element read can FAULT on this backend instead of + * yielding some value. The cpu backend emits plain JavaScript, where + * `a[y][x]` with `y` past the end throws a TypeError; every other backend + * reads a clamped texture or a bounds-checked buffer and cannot. The + * optimizer needs to know because moving a read to a place the un-optimized + * build never reaches is free where reads are total and a new crash where + * they are not. + * @returns {Boolean} + */ + get readsCanFault() { + return false; + } + + /** + * @desc Whether a SINGLE-subscript read can fault. On cpu `a[y]` past the + * end is `undefined` (only `a[y][x]` throws); on webasm every read is a + * raw load and one level is enough. + * @returns {Boolean} + */ + get readsFaultAtOneLevel() { + return false; + } + + /** + * @desc The parsed, de-minified AST -- everything getJsAST does BEFORE the + * optimizer and the tracer. T2's call-graph plan reads helpers through this + * rather than through getJsAST: optimizing a helper early would run its + * pass out of order, and tracing it early would resolve its argument types + * from a caller the un-optimized build resolves them from second. + * @param {Object} [inParser] + * @returns {Object} The function AST Object, cached under this._rawAST + */ + getRawAST(inParser) { + if (this._rawAST) { + return this._rawAST; } if (typeof this.source === 'object') { normalizeMinifiedStatements(this.source, this.requiresSequenceFreeForInit); - this.traceFunctionAST(this.source); - return this.ast = this.source; + return this._rawAST = this.source; } inParser = inParser || acorn; @@ -290,15 +339,47 @@ class FunctionNode { // minifiers fold statements into expressions; unfold them before the // tracer records anything, so every backend sees plain statements normalizeMinifiedStatements(functionAST, this.requiresSequenceFreeForInit); - this.traceFunctionAST(functionAST); + return this._rawAST = functionAST; + } - if (!ast) { - throw new Error('Failed to parse JS code'); + getJsAST(inParser) { + if (this.ast) { + return this.ast; } - + const functionAST = this.getRawAST(inParser); + // tagged so buildWithOptimizer retries only OUR failures: an + // unsupported-construct error from the emitter must reach the user + // unchanged, not be blamed on the optimizer and compiled twice + try { + this.optimizeAST(functionAST); + } catch (e) { + if (e && typeof e === 'object') e.isOptimizerFailure = true; + throw e; + } + this.traceFunctionAST(functionAST); return this.ast = functionAST; } + /** + * @desc The optimizer's single invocation point, shared by every emitting + * backend. It runs AFTER de-minification -- the pass must never see a + * comma-folded expression -- and BEFORE the tracer, so the declarations it + * introduces are the ones type resolution registers, and before every + * per-backend normalization (webgl's linearization and do-while rotation, + * webasm's variance analysis and SIMD emission), which must see final + * shapes. + * @param {Object} ast - the parsed function node + * @returns {Object} the same ast + */ + optimizeAST(ast) { + if (this.optimizerDisabled) return ast; + return optimize(this, ast, { + loopUnrollLimit: this.loopUnrollLimit, + lookupInlineTarget: this.lookupInlineTarget, + }); + } + + /** * @desc Argument names the function body assigns to. Backends whose * arguments are not plain per-invocation locals (the cpu backend's @@ -1233,8 +1314,15 @@ class FunctionNode { } if (uNode.prefix) { + // a leading sign needs parentheses of its own: the binary emitter puts + // no space around its operator, so `2 - -2` came out `2--2`, which is a + // syntax error in JavaScript and an l-value error in GLSL. `!` and `~` + // cannot collide with an adjacent operator and stay bare. + const collides = uNode.operator === '-' || uNode.operator === '+'; + if (collides) retArr.push('('); retArr.push(uNode.operator); this.astGeneric(uNode.argument, retArr); + if (collides) retArr.push(')'); } else { this.astGeneric(uNode.argument, retArr); retArr.push(uNode.operator); diff --git a/src/backend/kernel.js b/src/backend/kernel.js index 39db6dcd..bbe44ceb 100644 --- a/src/backend/kernel.js +++ b/src/backend/kernel.js @@ -243,6 +243,38 @@ class Kernel { this.strictIntegers = false; this.fixIntegerDivisionAccuracy = null; + /** + * Turns the compiler optimizations off for this kernel. Internal hook + * (the `_fusionDisabled` precedent), not a public setting: it exists so a + * build that throws can be redone honestly, and so the test suite can + * compare optimized emission against un-optimized emission. + * @type {Boolean} + */ + this._optimizerDisabled = false; + + /** + * Turns helper inlining (T2) off while leaving the rest of the pass on. + * Internal, like `_optimizerDisabled`, and for the same reason: the + * benchmark has to price one transform at a time, and `loopUnrollLimit` + * alone cannot separate inlining from hoisting. + * @type {Boolean} + */ + this._inliningDisabled = false; + /** + * T1, thread-coordinate localization -- off by default, a measured net + * loss at scale on this backend. See optimizer.threadLocalName. + */ + this.localizeThreadCoordinates = false; + + /** + * Trip-count threshold above which a loop with literal bounds is left as + * a loop rather than unrolled; `0` turns unrolling off. The knob to reach + * for when emitted size matters more than the loop overhead -- a mobile + * shader compiler charges for every copy. + * @type {Number} + */ + this.loopUnrollLimit = 8; + /** * Seed for Math.random() so kernel runs are reproducible; null seeds from Math.random() * @type {Number|null} @@ -537,6 +569,17 @@ class Kernel { return this; } + /** + * @desc Set the largest trip count a literal loop is unrolled at; `0` + * leaves every loop as written + * @param {number} limit - trip count threshold + * @return {this} + */ + setLoopUnrollLimit(limit) { + this.loopUnrollLimit = limit; + return this; + } + /** * @desc Set Constants * @return {this} @@ -809,6 +852,33 @@ class Kernel { return this.onRequestFallback(args); } + /** + * @desc Runs the source translation with the compiler optimizations on. A + * synchronous throw from an optimized build is our bug, not the user's, so + * the kernel redoes the translation with the optimizer off, says so loudly, + * and records why (#868). Runtime throws are never routed through here -- + * masking those helps nobody. + * @param {Function} work - the translation to run, re-runnable + * @returns {*} whatever `work` returns + */ + buildWithOptimizer(work) { + if (this._optimizerDisabled) return work(); + try { + return work(); + } catch (e) { + // the emitter's own errors (unsupported constructs, bad types) are the + // user's to see: rethrowing keeps the message honest and avoids + // compiling a doomed kernel twice + if (!e || !e.isOptimizerFailure) throw e; + this._optimizerDisabled = true; + this.fallbackReason = `compiler optimizations disabled: ${ e.message }`; + console.warn( + `gpu.js: compiling this kernel with compiler optimizations threw (${ e.message }); ` + + 'rebuilding with them off. Please report this at https://github.com/gpujs/gpu.js/issues'); + return work(); + } + } + /** * @desc Validate settings * @abstract diff --git a/src/backend/optimizer.js b/src/backend/optimizer.js new file mode 100644 index 00000000..d98f22a4 --- /dev/null +++ b/src/backend/optimizer.js @@ -0,0 +1,2240 @@ +/** + * @desc Backend-agnostic AST optimization pass, run at the FunctionBuilder + * stage by every function node that EMITS code. `dev` never reaches here -- + * gpu-mock runs the user's own function, so there is no emission to optimize. + * + * ORDERING IS LOAD-BEARING and owned by FunctionNode.getJsAST: de-minification + * unfolds statements FIRST (the pass must never see a comma-folded expression + * or a statement-position sequence), this runs second, and every per-backend + * normalization -- webgl's linearization and do-while rotation, webasm's + * variance analysis and SIMD emission -- sees the shapes this pass leaves + * behind. + * + * Every transform is PER-SITE best effort: whatever cannot be proven safe + * skips THAT site, never the tier. Un-transformed emission is always valid, + * which is what makes a bail cheap. + * + * The bar the output is held to is bitwise parity with the same kernel built + * with `_optimizerDisabled`, on that backend's own arithmetic. Nothing here + * reassociates floating point, changes how many times an operation runs, or + * moves a call -- so a seeded Math.random stream draws in exactly the same + * order either way. + */ + +/** + * Synthetic node positions. astKey and the literal-type cache are keyed by + * start/end, so every node this pass creates needs a unique pair. The + * 0x60000000 base is disjoint from real acorn offsets, from de-minification's + * 0x20000000 and from the webgl hoisting machinery's 0x40000000. + */ +let syntheticNodeId = 0x60000000; + +function stampSynthetic(node, source) { + node.start = syntheticNodeId++; + node.end = syntheticNodeId++; + if (source && source.loc) node.loc = source.loc; + return node; +} + +const scalarTypes = ['Number', 'Float', 'Integer']; + +const thisWrite = '@this'; + +const indexedReadSignatures = [ + 'value[]', + 'value[][]', + 'value[][][]', + 'value[][][][]', + 'this.constants.value[]', + 'this.constants.value[][]', + 'this.constants.value[][][]', + 'this.constants.value[][][][]', +]; + +/** + * @param {FunctionNode} functionNode + * @param {Object} ast - the function node's AST, already de-minified + * @param {IOptimizerSettings} [settings] + * @returns {Object} the same ast, transformed in place + */ +function optimize(functionNode, ast, settings) { + if (!ast || !ast.body || ast.body.type !== 'BlockStatement') return ast; + const context = new OptimizerContext(functionNode, ast, settings || {}); + // H then T2 then T3, as separate walks. Hoisting has to see loops while they + // are still loops and calls while they are still calls; inlining then + // exposes helper bodies to the unroller, which runs last so that a tiny + // loop an inlined body brought with it unrolls like any other. + processBlock(context, ast.body); + inlineBlock(context, ast.body); + unrollBlock(context, ast.body); + return ast; +} + +class OptimizerContext { + constructor(functionNode, ast, settings) { + this.functionNode = functionNode; + this.ast = ast; + this.loopUnrollLimit = typeof settings.loopUnrollLimit === 'number' ? settings.loopUnrollLimit : 8; + this.lookupInlineTarget = settings.lookupInlineTarget || null; + this.inlineTargets = new Map(); + this.inlineCount = 0; + // a name assigned, updated, declared or bound as a nested function's + // parameter ANYWHERE in this function stops counting as immutable, + // wherever the write sits relative to the read. The BODY only: this + // function's own parameters are the arrays the pass exists to read, and + // binding one is not a write to it + this.mutatedNames = collectMutatedNames(ast.body); + this.usedNames = collectUsedNames(ast); + this.hoistCount = 0; + } + + /** + * @returns {String} an identifier no source in this function uses. The + * emitters prefix it into their own namespace (`user_` on cpu and GL), so + * only a collision with a user identifier of the same spelling matters. + */ + freshName() { + let name; + do { + name = `optHoist${ this.hoistCount++ }`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + + /** + * @param {String} suffix - the helper's own spelling, kept so an emitted + * shader still reads like the source it came from + * @returns {String} a name for an inlined binding. The emitters own the + * `user_` prefix -- nothing at AST level can land outside it -- so + * collision-freedom comes from the same used-name check `freshName` uses, + * not from a reserved namespace. + */ + freshInlineName(suffix) { + let name; + do { + name = `optIn${ this.inlineCount++ }_${ suffix }`; + } while (this.usedNames.has(name)); + this.usedNames.add(name); + return name; + } + + /** + * @param {String} name + * @returns {Object|null} the call graph's verdict for a callee, cached per + * function so one build asks the builder once per name + */ + inlineTarget(name) { + if (!this.lookupInlineTarget) return null; + if (this.inlineTargets.has(name)) return this.inlineTargets.get(name); + let entry = null; + try { + entry = this.lookupInlineTarget(name) || null; + } catch (e) { + entry = null; + } + this.inlineTargets.set(name, entry); + return entry; + } + + /** + * @param {String} name + * @returns {Boolean} whether `name` is an array this function reads but can + * never write -- a kernel argument or constant that nothing assigns to and + * no local shadows. + */ + isImmutableArrayRoot(name) { + if (this.mutatedNames.has(name)) return false; + const { argumentNames } = this.functionNode; + return Boolean(argumentNames) && argumentNames.indexOf(name) > -1; + } + + /** + * The element type of a read, resolved without the tracer -- this pass runs + * before it. Mirrors FunctionNode.getType's one application of the lookup + * map to the ROOT's type, whatever the subscript depth. + * @param {Object} ast - a MemberExpression + * @param {String} signature + * @returns {String|null} null when the type is not yet known + */ + readElementType(ast, signature) { + const rootType = this.readRootType(ast, signature); + if (!rootType) return null; + try { + return this.functionNode.getLookupType(rootType); + } catch (e) { + // a type the lookup map does not know is a type this pass has no + // business guessing at + return null; + } + } + + /** + * The declared type of the array a read indexes into, or null when it is + * not yet known -- argument types resolve as the caller emits, so a helper + * consulted too early simply skips its sites. + * @param {Object} ast - a MemberExpression + * @param {String} signature + * @returns {String|null} + */ + readRootType(ast, signature) { + const { functionNode } = this; + if (signature.indexOf('this.constants.') === 0) { + if (this.mutatedNames.has(thisWrite)) return null; + const name = constantReadName(ast, signature); + if (!name) return null; + const type = functionNode.constantTypes ? functionNode.constantTypes[name] : null; + return type === 'Float' ? 'Number' : type || null; + } + const root = memberRoot(ast); + if (!root || root.type !== 'Identifier') return null; + if (!this.isImmutableArrayRoot(root.name)) return null; + const index = functionNode.argumentNames.indexOf(root.name); + return (functionNode.argumentTypes ? functionNode.argumentTypes[index] : null) || null; + } +} + +// --------------------------------------------------------------- traversal + +function walk(node, visit) { + if (!node || typeof node !== 'object') return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walk(node[i], visit); + return; + } + if (typeof node.type !== 'string') return; + visit(node); + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') walk(child, visit); + } +} + +/** + * `walk` that stops at a function boundary. A nested function is its own + * emitted function and its own plan entry, so the enclosing one must not + * count what happens inside it as its own. + */ +function walkOwn(node, visit) { + if (!node || typeof node !== 'object') return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) walkOwn(node[i], visit); + return; + } + if (typeof node.type !== 'string') return; + if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || + node.type === 'ArrowFunctionExpression') return; + visit(node); + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') walkOwn(child, visit); + } +} + +function collectMutatedNames(ast) { + const names = new Set(); + const addTarget = target => { + let node = target; + while (node && node.type === 'MemberExpression') node = node.object; + if (node && node.type === 'Identifier') names.add(node.name); + // a write through `this` (`this.constants.a[0] = x`, which the cpu + // backend really does perform) names no identifier to blame, so every + // constant stops counting as immutable + if (node && node.type === 'ThisExpression') names.add(thisWrite); + }; + walk(ast, node => { + switch (node.type) { + case 'AssignmentExpression': + addTarget(node.left); + break; + case 'UpdateExpression': + addTarget(node.argument); + break; + case 'VariableDeclarator': + if (node.id && node.id.type === 'Identifier') names.add(node.id.name); + break; + case 'FunctionDeclaration': + case 'FunctionExpression': + case 'ArrowFunctionExpression': + // a nested function's parameters rebind the name for its body; from + // out here that is indistinguishable from a write + if (node.id && node.id.name) names.add(node.id.name); + for (let i = 0; i < node.params.length; i++) { + if (node.params[i].type === 'Identifier') names.add(node.params[i].name); + } + break; + } + }); + return names; +} + +function collectUsedNames(ast) { + const names = new Set(); + walk(ast, node => { + if (node.type === 'Identifier') names.add(node.name); + }); + return names; +} + +function memberRoot(ast) { + let node = ast; + while (node && node.type === 'MemberExpression') node = node.object; + return node; +} + +/** + * @param {Object} ast - a MemberExpression with a `this.constants.` signature + * @param {String} signature + * @returns {String|null} the constant's name + */ +function constantReadName(ast, signature) { + let depth = (signature.match(/\[\]/g) || []).length; + let node = ast; + while (depth-- > 0) { + if (!node || node.type !== 'MemberExpression') return null; + node = node.object; + } + return node && node.property && node.property.name ? node.property.name : null; +} + +/** + * Walks a block, transforming inner scopes before their enclosing loop, so a + * read invariant to a whole loop nest ends up outside all of it. + */ +function processBlock(context, block) { + const body = block.body; + for (let i = 0; i < body.length; i++) { + const prefix = processStatement(context, body[i]); + if (prefix && prefix.length > 0) { + body.splice(i, 0, ...prefix); + i += prefix.length; + } + } +} + +/** + * @returns {Array|null} statements to place immediately before `statement` + */ +function processStatement(context, statement) { + switch (statement.type) { + case 'BlockStatement': + processBlock(context, statement); + return null; + case 'IfStatement': + processBranch(context, statement, 'consequent'); + processBranch(context, statement, 'alternate'); + return null; + case 'SwitchStatement': + for (let i = 0; i < statement.cases.length; i++) { + const block = { type: 'BlockStatement', body: statement.cases[i].consequent }; + processBlock(context, block); + statement.cases[i].consequent = block.body; + } + return null; + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + processBranch(context, statement, 'body'); + return hoistFromLoop(context, statement); + default: + return null; + } +} + +/** + * A single-statement position (an unbraced loop body or if branch) that gains + * hoisted declarations needs a block around them. + */ +function processBranch(context, statement, key) { + const branch = statement[key]; + if (!branch) return; + if (branch.type === 'BlockStatement') { + processBlock(context, branch); + return; + } + const prefix = processStatement(context, branch); + if (prefix && prefix.length > 0) { + statement[key] = stampSynthetic({ type: 'BlockStatement', body: prefix.concat([branch]) }, branch); + } +} + +// -------------------------------------------------- H: invariant read hoist + +/** + * H -- loop-invariant hoisting of pure reads. An array element read whose + * object and every subscript are loop-invariant moves to a fresh const before + * the loop. Legal precisely because a kernel cannot write its array + * arguments, so the value cannot change across iterations. + * + * Restricted to reads the body is GUARANTEED to reach: lifting a read the + * body might skip -- or that a loop running zero times never performs -- would + * evaluate it where the un-optimized build does not, and on cpu a multi-level + * read of an out-of-range index throws instead of yielding a number. That is a + * per-site skip, not a tier-wide one. + * + * @returns {Array} declarations to place immediately before the loop + */ +function hoistFromLoop(context, loop) { + const varying = collectMutatedNames(loop); + const entries = []; + collectReachable(loop.body, entries); + if (entries.length === 0) return []; + + // together with the reachability scan this is the whole safety argument: a + // read that the first iteration performs, in a loop that has a first + // iteration, is a read the un-optimized build performs too, so moving it + // ahead of the loop cannot introduce an evaluation -- or a fault -- that + // was not already there + const faultable = context.functionNode.readsCanFault && !loopIsAlwaysEntered(loop); + + const hoisted = []; + const relocated = new Set(); + const cache = new Map(); + for (let i = 0; i < entries.length; i++) { + const { statement } = entries[i]; + // a declaration this pass already made for an inner loop moves outward + // whole rather than being copied through a second temp + if (statement.optimizerHoist && isInvariant(context, statement.declarations[0].init, varying) && + !(faultable && canFault(context, statement.declarations[0].init))) { + const key = expressionKey(statement.declarations[0].init); + hoisted.push(statement); + relocated.add(statement); + if (key) cache.set(key, statement.declarations[0].id.name); + continue; + } + replaceInvariantReads(context, statement, varying, faultable, cache, hoisted); + } + + if (relocated.size > 0) { + for (let i = 0; i < entries.length; i++) { + const { list } = entries[i]; + if (!list.some(statement => relocated.has(statement))) continue; + const kept = list.filter(statement => !relocated.has(statement)); + list.length = 0; + for (let j = 0; j < kept.length; j++) list.push(kept[j]); + } + } + return hoisted; +} + +/** + * The statements a loop body reaches unconditionally on entry, each with the + * list it lives in so a relocated declaration can be spliced out. + * @returns {Boolean} whether control falls out of `list`'s end + */ +function collectReachableList(list, entries) { + for (let i = 0; i < list.length; i++) { + const statement = list[i]; + switch (statement.type) { + case 'ExpressionStatement': + case 'VariableDeclaration': + entries.push({ list, statement }); + break; + case 'EmptyStatement': + case 'DebuggerStatement': + break; + case 'BlockStatement': + if (!collectReachableList(statement.body, entries)) return false; + break; + case 'IfStatement': + case 'SwitchStatement': + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + // a construct that can transfer control out of the body ends the + // guaranteed region; one that cannot is simply stepped over + if (containsExit(statement)) return false; + break; + default: + return false; + } + } + return true; +} + +function collectReachable(body, entries) { + if (!body) return false; + if (body.type === 'BlockStatement') return collectReachableList(body.body, entries); + return collectReachableList([body], entries); +} + +/** + * @returns {Boolean} whether executing `statement` can transfer control past + * its own end -- a return anywhere, or a break/continue that binds to an + * enclosing loop rather than to something inside `statement`. + */ +function containsExit(statement) { + let found = false; + const visit = (node, inBreakable, inContinuable) => { + if (!node || typeof node !== 'object' || found) return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== 'string') return; + switch (node.type) { + case 'ReturnStatement': + case 'ThrowStatement': + found = true; + return; + case 'BreakStatement': + if (node.label || !inBreakable) found = true; + return; + case 'ContinueStatement': + if (node.label || !inContinuable) found = true; + return; + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + case 'SwitchStatement': + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + case 'FunctionDeclaration': + case 'FunctionExpression': + case 'ArrowFunctionExpression': + return; + } + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') visit(child, inBreakable, inContinuable); + } + }; + visit(statement, false, false); + return found; +} + +/** + * Rewrites every hoistable read inside one unconditionally reached statement. + * Does not descend into the parts of an expression that evaluate + * conditionally -- a ternary's branches, a short circuit's right operand -- + * for the same reason a read under an `if` does not hoist. + */ +function replaceInvariantReads(context, statement, varying, faultable, cache, hoisted) { + const visit = (node, key) => { + const child = node[key]; + if (!child || typeof child !== 'object') return; + if (Array.isArray(child)) { + for (let i = 0; i < child.length; i++) visit(child, i); + return; + } + if (typeof child.type !== 'string') return; + switch (child.type) { + case 'FunctionDeclaration': + case 'FunctionExpression': + case 'ArrowFunctionExpression': + return; + case 'ConditionalExpression': + visit(child, 'test'); + return; + case 'LogicalExpression': + visit(child, 'left'); + return; + case 'MemberExpression': + if (isHoistableRead(context, child, varying) && !(faultable && canFault(context, child))) { + node[key] = referenceFor(context, child, cache, hoisted); + return; + } + // only the OUTERMOST member of an index chain is ever a candidate: + // gpu.js types a partial index (`a[y]` of an Array2D) as a Number + // like the full one, but no backend can hold a row in a float + if (child.computed) visit(child, 'property'); + if (child.object && child.object.type !== 'MemberExpression') visit(child, 'object'); + return; + } + for (const childKey in child) { + if (childKey === 'loc' || childKey === 'range' || childKey === 'parent') continue; + const grandChild = child[childKey]; + if (grandChild && typeof grandChild === 'object') visit(child, childKey); + } + }; + const holder = { statement }; + visit(holder, 'statement'); +} + +function referenceFor(context, read, cache, hoisted) { + const key = expressionKey(read); + if (key && cache.has(key)) { + return stampSynthetic({ type: 'Identifier', name: cache.get(key) }, read); + } + const name = context.freshName(); + const declaration = stampSynthetic({ + type: 'VariableDeclaration', + kind: 'const', + declarations: [stampSynthetic({ + type: 'VariableDeclarator', + id: stampSynthetic({ type: 'Identifier', name }, read), + init: read, + }, read)], + }, read); + declaration.optimizerHoist = true; + hoisted.push(declaration); + if (key) cache.set(key, name); + return stampSynthetic({ type: 'Identifier', name }, read); +} + +/** + * @returns {Boolean} whether any read inside `ast` could throw where an + * un-optimized build would not have evaluated it at all. Only a chain of two + * or more real subscripts can: `a[y]` past the end of `a` is `undefined`, + * `a[y][x]` past the end throws. An `Input` argument is one flat buffer + * however many subscripts index it, so it is always the one-level case. + */ +function canFault(context, ast) { + let found = false; + walk(ast, node => { + if (found || node.type !== 'MemberExpression') return; + const signature = context.functionNode.getVariableSignature(node); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return; + if (!context.functionNode.readsFaultAtOneLevel && (signature.match(/\[\]/g) || []).length < 2) return; + if (context.readRootType(node, signature) === 'Input') return; + found = true; + }); + return found; +} + +/** + * @returns {Boolean} whether the loop provably runs its body at least once. + * Only literal bounds count -- the same criterion the unroller needs, so the + * two share it. + */ +function loopIsAlwaysEntered(loop) { + if (loop.type === 'DoWhileStatement') return true; + if (loop.type !== 'ForStatement') return false; + if (!loop.test) return true; + const { test } = loop; + if (test.type !== 'BinaryExpression' || test.left.type !== 'Identifier') return false; + const limit = literalNumber(test.right); + if (limit === null) return false; + const start = initialNumber(loop.init, test.left.name); + if (start === null) return false; + switch (test.operator) { + case '<': + return start < limit; + case '<=': + return start <= limit; + case '>': + return start > limit; + case '>=': + return start >= limit; + case '!==': + case '!=': + return start !== limit; + default: + return false; + } +} + +function literalNumber(ast) { + if (!ast) return null; + if (ast.type === 'Literal' && typeof ast.value === 'number') return ast.value; + if (ast.type === 'UnaryExpression' && ast.operator === '-') { + const value = literalNumber(ast.argument); + return value === null ? null : -value; + } + return null; +} + +function initialNumber(init, name) { + if (!init) return null; + if (init.type === 'VariableDeclaration') { + for (let i = 0; i < init.declarations.length; i++) { + const declaration = init.declarations[i]; + if (declaration.id.type === 'Identifier' && declaration.id.name === name) { + return literalNumber(declaration.init); + } + } + return null; + } + if (init.type === 'AssignmentExpression' && init.operator === '=' && + init.left.type === 'Identifier' && init.left.name === name) { + return literalNumber(init.right); + } + return null; +} + +/** + * @returns {Boolean} whether `ast` is a scalar element read of an array this + * function cannot write, indexed entirely by loop-invariant expressions. + */ +function isHoistableRead(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature || indexedReadSignatures.indexOf(signature) === -1) return false; + // a vec-valued read (`Array1D(4)` and friends) declares through a different + // path on every backend; phase 1 leaves those where they are + const elementType = context.readElementType(ast, signature); + if (!elementType || scalarTypes.indexOf(elementType) === -1) return false; + return isInvariant(context, ast, varying); +} + +/** + * @returns {Boolean} whether an expression evaluates to the same value on + * every iteration AND has no side effects. Anything with a call in it is not + * invariant here even if it looks pure: a helper may draw Math.random, and + * moving a draw would rewrite the seeded stream. + */ +function isInvariant(context, ast, varying) { + if (!ast || typeof ast !== 'object') return false; + switch (ast.type) { + case 'Literal': + return true; + case 'ThisExpression': + return true; + case 'Identifier': + return !varying.has(ast.name); + case 'UnaryExpression': + return ast.operator !== 'delete' && + ast.operator !== 'typeof' && + isInvariant(context, ast.argument, varying); + case 'BinaryExpression': + case 'LogicalExpression': + return isInvariant(context, ast.left, varying) && isInvariant(context, ast.right, varying); + case 'ConditionalExpression': + return isInvariant(context, ast.test, varying) && + isInvariant(context, ast.consequent, varying) && + isInvariant(context, ast.alternate, varying); + case 'MemberExpression': + return isInvariantMember(context, ast, varying); + default: + return false; + } +} + +function isInvariantMember(context, ast, varying) { + const signature = context.functionNode.getVariableSignature(ast); + if (!signature) return false; + switch (signature) { + case 'this.thread.value': + case 'this.output.value': + // fixed for the whole invocation + return true; + case 'this.constants.value': + return !context.mutatedNames.has(thisWrite); + case 'value.value': + // Math.PI and friends; a user value's `.r`/`.g`/`.b`/`.a` reads a local + // vec, which this pass does not track + return context.functionNode.isAstMathVariable(ast); + case 'value[]': + case 'value[][]': + case 'value[][][]': + case 'value[][][][]': { + const root = memberRoot(ast); + if (!root || root.type !== 'Identifier' || !context.isImmutableArrayRoot(root.name)) return false; + return everySubscriptInvariant(context, ast, varying); + } + case 'this.constants.value[]': + case 'this.constants.value[][]': + case 'this.constants.value[][][]': + case 'this.constants.value[][][][]': + if (context.mutatedNames.has(thisWrite)) return false; + return everySubscriptInvariant(context, ast, varying); + default: + return false; + } +} + +function everySubscriptInvariant(context, ast, varying) { + let node = ast; + while (node && node.type === 'MemberExpression') { + if (node.computed && !isInvariant(context, node.property, varying)) return false; + node = node.object; + } + return true; +} + +/** + * A structural key so two spellings of the same read share one hoisted const. + * Only reads collected from the same guaranteed region are ever compared, so + * this is common subexpression elimination over pure reads, not across float + * arithmetic. Returns null for anything it cannot canonicalize. + */ +function expressionKey(ast) { + if (!ast || typeof ast !== 'object') return null; + switch (ast.type) { + case 'Literal': + return `L${ typeof ast.value }:${ ast.value }`; + case 'ThisExpression': + return 'this'; + case 'Identifier': + return `#${ ast.name }`; + case 'MemberExpression': { + const object = expressionKey(ast.object); + const property = expressionKey(ast.property); + if (object === null || property === null) return null; + return `M${ ast.computed ? '[' : '.' }(${ object },${ property })`; + } + case 'UnaryExpression': { + const argument = expressionKey(ast.argument); + return argument === null ? null : `U${ ast.operator }(${ argument })`; + } + case 'BinaryExpression': + case 'LogicalExpression': { + const left = expressionKey(ast.left); + const right = expressionKey(ast.right); + if (left === null || right === null) return null; + return `B${ ast.operator }(${ left },${ right })`; + } + default: + return null; + } +} + +// ----------------------------------------------------------- T2: inlining + +/** + * T2 -- helper inlining. A call to a user helper is replaced by the helper's + * body: its parameters bound as fresh declarations in source order, its locals + * renamed, and the expression it returned left where the call was. + * + * The win is largest on webasm and it is not call overhead. The SIMD emitter + * has no vector form for a helper call, so it lane-scalarizes one: thread + * state and PCG state swap per lane, the arguments are extracted lane by lane + * and the scalar function runs four times per quad. A helper in a hot loop + * therefore un-vectorizes the loop that contains it. Inlining restores the + * vector form, which is why this transform is worth its correctness surface. + * + * THE DECISION IS GLOBAL, not per site. A helper left with some call sites + * inlined and others not still gets emitted, and gpu.js fixes a helper's + * parameter types from whichever call site the emitter reaches FIRST -- + * removing a site can change which one that is, and with it what the surviving + * sites coerce their arguments to. `buildInlinePlan` therefore decides + * inlinability for the whole call graph before any function node is optimized, + * all-or-nothing per helper; a site this pass cannot hoist disqualifies its + * helper everywhere rather than leaving a mixed build. + */ + +// a single helper's expanded body, and the total a single function may gain. +// The first keeps one bad helper from dominating a shader; the second keeps a +// deep call graph from producing a megafunction (V8 stops inlining and +// eventually deoptimizes; mobile shader compilers get slower superlinearly) +const INLINE_MAX_HELPER_NODES = 320; +const INLINE_MAX_ADDED_NODES = 6000; + +// unrolling nests multiplicatively -- depth d costs limit^d copies -- so the +// per-loop trip count is not a bound on the emitted size. The cumulative cap +// is T2's, for the same reason: past it, cpu deoptimizes and GL shader +// compilation grows superlinearly (#8 of the build review). +const UNROLL_MAX_ADDED_NODES = 6000; + +// an expansion is bounded by the plan's budgets, so a walk that keeps finding +// work past this has a bug in it rather than a big kernel; the #868 contract +// turns the throw into an un-optimized build +const INLINE_MAX_STATEMENTS = 20000; + +function inlineBlock(context, block) { + if (!context.lookupInlineTarget) return; + block.body = inlineList(context, block.body); +} + +/** + * Rewrites one statement list. An expansion is pushed back onto the pending + * queue rather than straight to the output, so a helper that calls a helper + * expands one level per pass until nothing inlinable is left -- the leaf-first + * order the plan already computed its budgets in. + */ +function inlineList(context, list) { + const out = []; + const pending = list.slice(); + let guard = 0; + while (pending.length > 0) { + if (++guard > INLINE_MAX_STATEMENTS) { + throw new Error('optimizer: inlining did not converge'); + } + const statement = pending.shift(); + const prefix = []; + const expansion = inlineStatementOwn(context, statement, prefix); + if (expansion.expanded > 0) { + // re-queued rather than emitted: an expansion whose arguments were all + // atoms adds no statements at all, and its own calls still have to be + // seen + const replacement = expansion.consumed ? + stampSynthetic({ type: 'EmptyStatement' }, statement) : statement; + pending.unshift(...prefix, replacement); + continue; + } + inlineStatementChildren(context, statement); + out.push(statement); + } + return out; +} + +function inlineStatementChildren(context, statement) { + switch (statement.type) { + case 'BlockStatement': + inlineBlock(context, statement); + return; + case 'IfStatement': + statement.consequent = inlineBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = inlineBranch(context, statement.alternate); + return; + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + statement.body = inlineBranch(context, statement.body); + return; + case 'SwitchStatement': + for (let i = 0; i < statement.cases.length; i++) { + statement.cases[i].consequent = inlineList(context, statement.cases[i].consequent); + } + return; + } +} + +/** + * A single-statement position that gains the statements of an expansion needs + * a block around them. + */ +function inlineBranch(context, branch) { + if (!branch) return branch; + if (branch.type === 'BlockStatement') { + inlineBlock(context, branch); + return branch; + } + const replacement = inlineList(context, [branch]); + if (replacement.length === 1 && replacement[0] === branch) return branch; + return stampSynthetic({ type: 'BlockStatement', body: replacement }, branch); +} + +/** + * Expands every hoistable call in one statement's own expressions. + * @returns {{expanded: Number, consumed: Boolean}} how many calls were + * expanded, and whether the statement itself is now redundant -- a call that + * WAS the statement leaves its value in a declaration instead + */ +function inlineStatementOwn(context, statement, prefix) { + const sites = collectStatementSites(context, statement); + let consumed = false; + for (let i = 0; i < sites.length; i++) { + if (expandCall(context, sites[i], prefix)) consumed = true; + } + return { expanded: sites.length, consumed }; +} + +/** + * The call sites in one statement this pass may hoist, in evaluation order. + * Shared with the plan, which is what makes the plan's verdict and this walk + * agree about which sites exist. + */ +function collectStatementSites(context, statement) { + const scan = { candidates: name => context.inlineTarget(name), sites: [], clean: true }; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) { + scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + } + return scan.sites; +} + +/** + * The expression positions of a statement that run exactly once, in order. + * A loop's test and update run per iteration and a do-while's test runs after + * the body, so neither can be prefixed by anything; calls there keep their + * call. + */ +function statementValueRoots(statement) { + switch (statement.type) { + case 'ExpressionStatement': + return [{ parent: statement, key: 'expression', statementPosition: true }]; + case 'ReturnStatement': + return statement.argument ? [{ parent: statement, key: 'argument' }] : []; + case 'IfStatement': + return [{ parent: statement, key: 'test' }]; + case 'SwitchStatement': + return [{ parent: statement, key: 'discriminant' }]; + case 'VariableDeclaration': + return declarationRoots(statement); + case 'ForStatement': + if (!statement.init) return []; + if (statement.init.type === 'VariableDeclaration') return declarationRoots(statement.init); + return [{ parent: statement, key: 'init' }]; + default: + return []; + } +} + +function declarationRoots(declaration) { + const roots = []; + for (let i = 0; i < declaration.declarations.length; i++) { + if (declaration.declarations[i].init) { + roots.push({ parent: declaration.declarations[i], key: 'init' }); + } + } + return roots; +} + +/** + * Walks an expression in EVALUATION order looking for calls to hoist. A call + * may only move to a statement before this one when everything the statement + * evaluates first has no effect of its own: hoisting past an assignment, an + * update or another call would reorder them, and a helper that draws + * Math.random reorders the seeded stream by moving at all. + * + * Conditionally evaluated operands -- a ternary's branches, a short circuit's + * right side -- are never descended into: a call there does not run every + * time, and there is nowhere unconditional to hoist it to. + */ +function scanValue(parent, key, scan, statementPosition, objectPosition) { + const node = parent[key]; + if (!node || typeof node !== 'object' || typeof node.type !== 'string') return; + switch (node.type) { + case 'Literal': + case 'Identifier': + case 'ThisExpression': + return; + case 'MemberExpression': + // `fn()[...]` is a signature of its own on every backend -- an emitted + // helper does the indexing, because GLSL ES 1.00 will not subscript a + // matrix with a non-constant expression. Replacing the call with a + // binding takes a different path through the emitter, so the site is + // left alone. + scanValue(node, 'object', scan, false, node.object && node.object.type === 'CallExpression'); + if (node.computed) scanValue(node, 'property', scan, false); + return; + case 'UnaryExpression': + scanValue(node, 'argument', scan, false); + return; + case 'BinaryExpression': + scanValue(node, 'left', scan, false); + scanValue(node, 'right', scan, false); + return; + case 'LogicalExpression': + scanValue(node, 'left', scan, false); + scanConditional(node.right, scan); + return; + case 'ConditionalExpression': + scanValue(node, 'test', scan, false); + scanConditional(node.consequent, scan); + scanConditional(node.alternate, scan); + return; + case 'ArrayExpression': + for (let i = 0; i < node.elements.length; i++) scanValue(node.elements, i, scan, false); + return; + case 'SequenceExpression': + for (let i = 0; i < node.expressions.length; i++) scanValue(node.expressions, i, scan, false); + return; + case 'AssignmentExpression': + // the target's own subscripts evaluate before the value; the write + // itself happens after + if (node.left.type === 'MemberExpression') scanValue(node, 'left', scan, false); + scanValue(node, 'right', scan, false); + scan.clean = false; + return; + case 'UpdateExpression': + scan.clean = false; + return; + case 'CallExpression': { + for (let i = 0; i < node.arguments.length; i++) scanValue(node.arguments, i, scan, false); + const name = inlineCalleeName(node); + const entry = name ? scan.candidates(name) : null; + if (entry && !objectPosition) { + // a helper that returns nothing has no value to leave behind, so it + // only inlines where the call WAS the statement + if (scan.clean && (entry.returnsValue || statementPosition)) { + scan.sites.push({ parent, key, node, entry, statementPosition }); + // expanding a site lifts its body into the shared prefix ahead of + // the statement, so a SECOND site in the same statement runs its + // body before this site's returned expression is used. Harmless for + // a pure helper (bindings and an expression, reordered invisibly), + // but for one that DRAWS RANDOM it permutes the seeded stream -- + // and for one that assigns outward it reorders the writes (#6). + if (entry.hasEffects) scan.clean = false; + return; + } + scan.clean = false; + return; + } + if (!isPureMathCall(node)) scan.clean = false; + return; + } + default: + // an unrecognized expression is opaque: nothing after it hoists + scan.clean = false; + } +} + +/** + * A conditionally evaluated operand. Nothing inside it can hoist, and if it + * can do anything at all then nothing after it can hoist either. + */ +function scanConditional(node, scan) { + walk(node, child => { + if (child.type === 'CallExpression') { + if (!isPureMathCall(child)) scan.clean = false; + return; + } + if (child.type === 'AssignmentExpression' || child.type === 'UpdateExpression') scan.clean = false; + }); +} + +/** + * @returns {String|null} the helper name a call names directly. `Math.x()`, + * `this.x()` and a sub-kernel reached through a member expression all have a + * callee this pass does not inline. + */ +function inlineCalleeName(ast) { + return ast.callee && ast.callee.type === 'Identifier' ? ast.callee.name : null; +} + +/** + * @returns {Boolean} whether a call is one of the Math functions that compute + * from their arguments alone. `Math.random` is the exception that matters: it + * carries generator state, so its position in the statement is observable. + */ +function isPureMathCall(ast) { + const { callee } = ast; + return Boolean(callee) && callee.type === 'MemberExpression' && !callee.computed && + callee.object && callee.object.type === 'Identifier' && callee.object.name === 'Math' && + callee.property && callee.property.name !== 'random'; +} + +/** + * Replaces one call with the helper's body. + * @returns {Boolean} whether the statement holding the call is now redundant + */ +function expandCall(context, site, prefix) { + const { node, entry, parent, key } = site; + const bindings = new Map(); + // parameters bind in SOURCE ORDER, one binding per argument, each evaluated + // exactly once -- the order and the count a call would have had + for (let i = 0; i < entry.params.length; i++) { + const param = entry.params[i]; + const argument = node.arguments[i]; + if (!entry.assignedParams.has(param) && isInlineAtom(context, argument)) { + // an atom has no effect and cannot change while the body runs, so the + // body may read it in place as many times as it names the parameter + bindings.set(param, { atom: argument, name: null }); + continue; + } + const name = context.freshInlineName(param); + prefix.push(inlineDeclaration(entry.assignedParams.has(param) ? 'let' : 'const', name, argument)); + bindings.set(param, { atom: null, name }); + } + // an argument the helper has no parameter for is still evaluated by a call + for (let i = entry.params.length; i < node.arguments.length; i++) { + prefix.push(inlineDeclaration('const', context.freshInlineName('arg'), node.arguments[i])); + } + + const renames = new Map(); + entry.localNames.forEach(local => { + renames.set(local, context.freshInlineName(local)); + }); + + const body = cloneInlineNodes(context, entry.body, bindings, renames); + const reduced = reduceReturns(body); + if (!reduced) throw new Error(`optimizer: helper body no longer reduces`); + for (let i = 0; i < reduced.statements.length; i++) prefix.push(reduced.statements[i]); + + if (site.statementPosition) { + // the value is discarded, but a call evaluated it -- keeping the + // declaration keeps every read and draw inside it happening + if (reduced.value !== null) { + prefix.push(inlineDeclaration('const', context.freshInlineName('ret'), reduced.value)); + } + return true; + } + parent[key] = reduced.value; + return false; +} + +function inlineDeclaration(kind, name, init) { + return stampSynthetic({ + type: 'VariableDeclaration', + kind, + declarations: [stampSynthetic({ + type: 'VariableDeclarator', + id: stampSynthetic({ type: 'Identifier', name }, init), + init, + }, init)], + }, init); +} + +/** + * @returns {Boolean} whether an argument can simply be written wherever the + * body names its parameter: no effect to run twice, no value that can change + * while the body runs, and nothing that can fault. + */ +function isInlineAtom(context, ast) { + if (!ast || typeof ast !== 'object') return false; + switch (ast.type) { + case 'Literal': + return true; + case 'Identifier': + // a helper cannot see the caller's locals, so nothing the body does can + // change what this identifier reads + return true; + case 'UnaryExpression': + return (ast.operator === '-' || ast.operator === '+') && ast.argument.type === 'Literal'; + case 'MemberExpression': + try { + switch (context.functionNode.getVariableSignature(ast)) { + case 'this.thread.value': + case 'this.output.value': + return true; + case 'this.constants.value': + return !context.mutatedNames.has(thisWrite); + case 'value.value': + return context.functionNode.isAstMathVariable(ast); + default: + return false; + } + } catch (e) { + return false; + } + default: + return false; + } +} + +/** + * A deep copy of a helper body with its parameters bound and its locals + * renamed. Every node is stamped a fresh position: astKey and the literal-type + * cache are keyed by start/end, so two expansions of one helper sharing a + * position would share a type decision made for one of them. + */ +function cloneInlineNodes(context, nodes, bindings, renames) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneInlineNode(context, nodes[i], bindings, renames); + return result; +} + +function cloneInlineNode(context, node, bindings, renames) { + if (!node || typeof node !== 'object') return node; + if (Array.isArray(node)) return cloneInlineNodes(context, node, bindings, renames); + if (typeof node.type !== 'string') return node; + if (node.type === 'Identifier') { + const bound = bindings.get(node.name); + if (bound) { + return bound.atom ? + cloneNode(context, bound.atom, null, 0) : + stampSynthetic({ type: 'Identifier', name: bound.name }, node); + } + const renamed = renames.get(node.name); + return stampSynthetic({ type: 'Identifier', name: renamed || node.name }, node); + } + const copy = {}; + // a non-computed member's property is a field name, not a variable + const verbatimProperty = node.type === 'MemberExpression' && !node.computed; + for (const key in node) { + if (key === 'start' || key === 'end') continue; + if (key === 'loc' || key === 'range' || key === 'parent') { + copy[key] = node[key]; + continue; + } + copy[key] = verbatimProperty && key === 'property' ? + cloneNode(context, node[key], null, 0) : + cloneInlineNode(context, node[key], bindings, renames); + } + return stampSynthetic(copy, node); +} + +/** + * Reduces a helper body to statements plus the one expression it returns. + * + * A body whose only return is its last statement needs nothing: the statements + * run, and the return's expression is what the call site gets. An EARLY return + * is folded instead of flagged -- `if (c) return A; return B;` becomes the + * conditional `c ? A : B`, which evaluates exactly the branch the function + * would have. The labeled-block idiom the cpu backend uses for the kernel body + * is deliberately not used here: GLSL has no labeled break, so it does not + * port to three of the four emitting tiers, and a result temp would have to + * declare a type this pass has no way to ask for (the optimizer runs before + * the tracer, so nothing is typed yet). + * + * @returns {{statements: Array, value: Object|null}|null} null when the body + * returns from somewhere this cannot fold + */ +function reduceReturns(statements) { + let first = -1; + for (let i = 0; i < statements.length; i++) { + if (containsReturn(statements[i])) { + first = i; + break; + } + } + if (first === -1) return { statements, value: null }; + const value = tailExpression(statements, first); + if (value === null) return null; + return { statements: statements.slice(0, first), value }; +} + +function tailExpression(list, i) { + if (i >= list.length) return null; + const statement = list[i]; + if (statement.type === 'ReturnStatement') { + // anything after a return is unreachable; rather than reason about what + // may be dropped, this shape is left alone + if (i !== list.length - 1 || !statement.argument) return null; + return statement.argument; + } + if (statement.type !== 'IfStatement') return null; + const consequent = branchExpression(statement.consequent); + if (consequent === null) return null; + let alternate; + if (statement.alternate) { + if (i !== list.length - 1) return null; + alternate = branchExpression(statement.alternate); + } else { + alternate = tailExpression(list, i + 1); + } + if (alternate === null) return null; + // the folded branches become operands of a conditional, and the webasm SIMD + // emitter evaluates both sides of one for every lane before selecting. A + // call in a branch would therefore run where the function never ran it -- + // and for Math.random that is a different stream. + if (!isBranchSafe(consequent) || !isBranchSafe(alternate)) return null; + // GLSL has no implicit int/float conversion, so a fold whose branches + // resolve to different types emits `cond ? int : float` and fails to + // compile (#3 of the build review). The types are not known until tracing, + // so the conservative proxy is literal shape: an integer literal on one + // side and a fractional one on the other is exactly the failing case. + const consequentKind = branchLiteralKind(consequent); + const alternateKind = branchLiteralKind(alternate); + if (consequentKind !== 'unknown' && alternateKind !== 'unknown' && + consequentKind !== alternateKind) return null; + return stampSynthetic({ + type: 'ConditionalExpression', + test: statement.test, + consequent, + alternate, + }, statement); +} + +/** + * @returns {String} 'int' | 'float' | 'unknown' -- the literal shape a folded + * branch would carry into a ternary. Only a definite disagreement blocks the + * fold; 'unknown' matches anything, since the emitter resolves those itself. + */ +function branchLiteralKind(ast) { + if (!ast) return 'unknown'; + if (ast.type === 'Literal' && typeof ast.value === 'number') { + return Number.isInteger(ast.value) ? 'int' : 'float'; + } + if (ast.type === 'BinaryExpression' && '+-*/'.indexOf(ast.operator) > -1) { + const left = branchLiteralKind(ast.left); + const right = branchLiteralKind(ast.right); + if (left === 'float' || right === 'float') return 'float'; + if (left === 'unknown' || right === 'unknown') return 'unknown'; + return ast.operator === '/' ? 'unknown' : 'int'; + } + return 'unknown'; +} + +function branchExpression(branch) { + if (!branch) return null; + return tailExpression(branch.type === 'BlockStatement' ? branch.body : [branch], 0); +} + +function containsReturn(ast) { + let found = false; + walk(ast, node => { + if (node.type === 'ReturnStatement') found = true; + }); + return found; +} + +function isBranchSafe(ast) { + let safe = true; + walk(ast, node => { + if (node.type === 'CallExpression' && !isPureMathCall(node)) safe = false; + }); + return safe; +} + +// --------------------------------------------------------- T2: the call graph + +/** + * Decides, for a whole FunctionBuilder at once, which helpers T2 may inline. + * Called once per build, before any function node is optimized. + * + * Everything here reads RAW ASTs -- parsed and de-minified, never optimized or + * traced. Tracing a helper early would resolve its argument types from a + * caller the un-optimized build resolves them from second, which is exactly + * the difference this pass exists not to make. + * + * @param {FunctionBuilder} builder + * @returns {Map} name -> plan entry, only for helpers every + * one of whose call sites will be inlined + */ +function buildInlinePlan(builder) { + const entries = new Map(); + const kernel = builder.kernel || {}; + const allowedFree = new Set(['Math', 'Infinity']); + if (kernel.constants) { + for (const name in kernel.constants) allowedFree.add(name); + } + for (let i = 0; i < builder.nativeFunctionNames.length; i++) { + allowedFree.add(builder.nativeFunctionNames[i]); + } + + for (const name in builder.functionMap) { + const node = builder.functionMap[name]; + if (!node) continue; + let ast = null; + try { + ast = node.getRawAST(); + } catch (e) { + // a helper whose source will not parse fails loudly at emission, where + // the error names the function; it must not fail here instead + ast = null; + } + if (!ast || !ast.body || ast.body.type !== 'BlockStatement') continue; + // a native function of the same name WINS at emission, deliberately, so + // the JavaScript body registered under that name is not what the call + // site runs and must never be what it inlines + const shadowed = builder.nativeFunctionNames.indexOf(name) > -1; + // addFunction's declared returnType/argumentTypes are coercions the + // emitter applies at the call boundary; inlining deletes the boundary and + // with it the coercion, so a declared helper keeps its call + const declaredTypes = Boolean(node.hasDeclaredTypes); + const kind = node.isRootKernel ? 'root' : + (node.isSubKernel || shadowed || declaredTypes ? 'subKernel' : 'helper'); + registerPlanEntry(entries, name, ast, kind, allowedFree); + } + + // gpu.js fixes a helper's parameter types from the FIRST call site the + // emitter reaches, and every later site is coerced into them. Inlining + // gives each site its own types, so a helper called with `Integer` at one + // site and `Number` at another computes differently once inlined (#2 of + // the build review). Multi-site helpers therefore keep their calls unless + // every site passes arguments of the same shape -- which the plan cannot + // know before tracing, so the conservative rule is: one site inlines. + for (const entry of entries.values()) allowedFree.add(entry.name); + for (const entry of entries.values()) analyzePlanEntry(entry, allowedFree); + // effects propagate along the call graph: a pure-looking helper that calls + // a drawing one is effectful at ITS call sites too + let effectsChanged = true; + while (effectsChanged) { + effectsChanged = false; + for (const entry of entries.values()) { + if (entry.hasEffects) continue; + for (let i = 0; i < entry.calls.length; i++) { + const callee = entries.get(entry.calls[i]); + if (callee && callee.hasEffects) { + entry.hasEffects = true; + effectsChanged = true; + break; + } + } + } + } + markRecursive(entries); + + // the site scan classifies a call by whether its callee is still a + // candidate, so disqualifying one can change how another site reads; the + // scan repeats until the candidate set stops shrinking + let changed = true; + while (changed) { + changed = false; + for (const entry of entries.values()) entry.sites = []; + const blocked = new Set(); + for (const entry of entries.values()) scanPlanEntry(entries, entry, blocked); + for (const name of blocked) { + const entry = entries.get(name); + if (entry && entry.inlinable) { + entry.inlinable = false; + changed = true; + } + } + // a helper the budget sheds keeps its call sites, and a surviving call is + // an effect the scan has to see -- so the budget runs inside the fixed + // point, not after it + if (!changed && applyInlineBudget(entries)) changed = true; + } + + const plan = new Map(); + for (const entry of entries.values()) { + if (!entry.inlinable) continue; + plan.set(entry.name, { + params: entry.params, + body: entry.body, + assignedParams: entry.assignedParams, + localNames: entry.localNames, + returnsValue: entry.returnsValue, + }); + } + // multi-site helpers keep their calls: the emitter's first-site parameter + // type fixing is a coercion inlining would delete (#2) + for (const entry of entries.values()) { + if (entry.inlinable && entry.sites.length > 1) { + entry.inlinable = false; + entry.sites = []; + } + } + + return plan; +} + +function registerPlanEntry(entries, name, ast, kind, allowedFree) { + if (!entries.has(name)) { + entries.set(name, { + name, + ast, + kind, + params: (ast.params || []).map(param => (param.type === 'Identifier' ? param.name : null)), + body: ast.body.body, + assignedParams: new Set(), + localNames: new Set(), + returnsValue: false, + inlinable: kind === 'helper', + recursive: false, + calls: [], + sites: [], + selfSize: 0, + expandedSize: 0, + }); + } + // a function declared inside another is its own emitted function; register + // it so its calls are graph edges, and refuse to inline the one that + // declares it (nested functions are registered by AST identity, so a clone + // would register the same helper twice) + const nested = []; + walk(ast.body, node => { + if (node.type === 'FunctionDeclaration' && node.id && node.id.name) nested.push(node); + }); + for (let i = 0; i < nested.length; i++) { + registerPlanEntry(entries, nested[i].id.name, nested[i], 'helper', allowedFree); + } +} + +/** + * The structural verdict on one helper, independent of its call sites. + */ +function analyzePlanEntry(entry, allowedFree) { + entry.selfSize = nodeCount(entry.body); + const declared = new Set(); + const assigned = new Set(); + const free = new Set(); + let rejected = false; + // a draw advances a seeded stream, so its POSITION is observable + let hasEffects = false; + walk(entry.body, node => { + if (node.type === 'CallExpression' && node.callee && + node.callee.type === 'MemberExpression' && node.callee.object && + node.callee.object.name === 'Math' && node.callee.property && + node.callee.property.name === 'random') { + hasEffects = true; + } + }); + + const visit = node => { + if (!node || typeof node !== 'object') return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== 'string') return; + switch (node.type) { + case 'LabeledStatement': + rejected = true; + return; + case 'FunctionDeclaration': + case 'FunctionExpression': + case 'ArrowFunctionExpression': + rejected = true; + return; + case 'VariableDeclarator': + if (node.id && node.id.type === 'Identifier') declared.add(node.id.name); + break; + case 'AssignmentExpression': + if (node.left.type === 'Identifier') assigned.add(node.left.name); + break; + case 'UpdateExpression': + if (node.argument.type === 'Identifier') assigned.add(node.argument.name); + break; + case 'Identifier': + free.add(node.name); + break; + case 'MemberExpression': + visit(node.object); + if (node.computed) visit(node.property); + return; + } + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') visit(child); + } + }; + visit(entry.body); + + for (let i = 0; i < entry.params.length; i++) { + if (entry.params[i] === null) rejected = true; + } + if (rejected) { + entry.inlinable = false; + return; + } + for (const name of free) { + if (declared.has(name) || entry.params.indexOf(name) > -1 || allowedFree.has(name)) continue; + // an identifier the helper does not declare would bind to whatever the + // caller happens to have named that -- capture, not inlining + entry.inlinable = false; + return; + } + entry.localNames = declared; + for (let i = 0; i < entry.params.length; i++) { + if (assigned.has(entry.params[i])) entry.assignedParams.add(entry.params[i]); + } + // a write to anything the helper did not declare itself escapes the + // expansion, so its position relative to a sibling site is observable + for (const name of assigned) { + if (!declared.has(name) && entry.params.indexOf(name) === -1) hasEffects = true; + } + entry.hasEffects = hasEffects; + const reduced = reduceReturns(entry.body); + if (!reduced) { + entry.inlinable = false; + return; + } + entry.returnsValue = reduced.value !== null; + if (entry.selfSize > INLINE_MAX_HELPER_NODES) entry.inlinable = false; +} + +/** + * Records the graph edges out of one function and blocks any callee whose call + * site this pass cannot hoist. + */ +function scanPlanEntry(entries, entry, blocked) { + const candidates = name => { + const target = entries.get(name); + return target && target.inlinable && !target.recursive ? target : null; + }; + const hoisted = new Set(); + const scan = { candidates, sites: [], clean: true }; + const walkStatements = list => { + for (let i = 0; i < list.length; i++) walkStatement(list[i]); + }; + const walkStatement = statement => { + if (!statement || typeof statement.type !== 'string') return; + if (statement.type === 'FunctionDeclaration') return; + scan.clean = true; + scan.sites = []; + const roots = statementValueRoots(statement); + for (let i = 0; i < roots.length; i++) { + scanValue(roots[i].parent, roots[i].key, scan, Boolean(roots[i].statementPosition)); + } + for (let i = 0; i < scan.sites.length; i++) { + hoisted.add(scan.sites[i].node); + entry.sites.push(scan.sites[i]); + } + switch (statement.type) { + case 'BlockStatement': + walkStatements(statement.body); + return; + case 'IfStatement': + walkStatement(statement.consequent); + if (statement.alternate) walkStatement(statement.alternate); + return; + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + walkStatement(statement.body); + return; + case 'SwitchStatement': + for (let i = 0; i < statement.cases.length; i++) walkStatements(statement.cases[i].consequent); + return; + } + }; + walkStatements(entry.body); + + // EVERY call this walk did not claim -- in a conditional operand, behind an + // effect, in a loop test, inside a helper's own unreachable corner -- keeps + // its call, and a helper with one surviving call site is a helper the + // emitter still types from whichever site it reaches first. That is what + // makes inlining all-or-nothing rather than per site. + walkOwn(entry.body, node => { + if (node.type !== 'CallExpression' || hoisted.has(node)) return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) blocked.add(name); + }); + for (let i = 0; i < entry.sites.length; i++) { + const site = entry.sites[i]; + if (site.node.arguments.length < site.entry.params.length) blocked.add(site.entry.name); + for (let j = 0; j < site.node.arguments.length; j++) { + if (site.node.arguments[j].type === 'SpreadElement') blocked.add(site.entry.name); + } + } +} + +function markRecursive(entries) { + const edges = new Map(); + for (const entry of entries.values()) { + const out = new Set(); + walkOwn(entry.body, node => { + if (node.type !== 'CallExpression') return; + const name = inlineCalleeName(node); + if (name && entries.has(name)) out.add(name); + }); + edges.set(entry.name, out); + } + const state = new Map(); + const onStack = []; + const visit = name => { + if (state.get(name) === 'done') return; + if (state.get(name) === 'open') { + // everything from the repeat of `name` on the stack is one cycle + for (let i = onStack.lastIndexOf(name); i < onStack.length; i++) { + entries.get(onStack[i]).recursive = true; + entries.get(onStack[i]).inlinable = false; + } + return; + } + state.set(name, 'open'); + onStack.push(name); + for (const next of edges.get(name) || []) visit(next); + onStack.pop(); + state.set(name, 'done'); + }; + for (const name of entries.keys()) visit(name); +} + +/** + * The emitted-size budget. Expanded sizes are computed leaf-first, then any + * caller that would gain more than the budget sheds its largest inlinable + * callee -- globally, since inlining is all-or-nothing per helper. Largest + * first, ties by name, so the outcome does not depend on map order. + */ +function applyInlineBudget(entries) { + let bounded = false; + let shed = false; + while (!bounded) { + computeExpandedSizes(entries); + for (const entry of entries.values()) { + if (entry.inlinable && entry.expandedSize > INLINE_MAX_HELPER_NODES) { + entry.inlinable = false; + shed = true; + } + } + bounded = true; + let worst = null; + let worstAdded = INLINE_MAX_ADDED_NODES; + for (const entry of entries.values()) { + let added = 0; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) added += callee.expandedSize; + } + if (added > worstAdded) { + worstAdded = added; + worst = entry; + } + } + if (!worst) break; + let victim = null; + for (let i = 0; i < worst.sites.length; i++) { + const callee = entries.get(worst.sites[i].entry.name); + if (!callee || !callee.inlinable) continue; + if (!victim || callee.expandedSize > victim.expandedSize || + (callee.expandedSize === victim.expandedSize && callee.name < victim.name)) { + victim = callee; + } + } + if (!victim) break; + victim.inlinable = false; + shed = true; + bounded = false; + } + return shed; +} + +function computeExpandedSizes(entries) { + const pending = new Set(entries.keys()); + for (const entry of entries.values()) entry.expandedSize = entry.selfSize; + // acyclic among the inlinable, so a fixed number of relaxations settles it + for (let round = 0; round < pending.size + 1; round++) { + let changed = false; + for (const entry of entries.values()) { + let size = entry.selfSize; + for (let i = 0; i < entry.sites.length; i++) { + const callee = entries.get(entry.sites[i].entry.name); + if (callee && callee.inlinable) size += callee.expandedSize; + } + if (size !== entry.expandedSize) { + entry.expandedSize = size; + changed = true; + } + } + if (!changed) break; + } +} + +function nodeCount(ast) { + let count = 0; + walk(ast, () => { + count++; + }); + return count; +} + +// ------------------------------------------------------- T3: literal unroll + +/** + * T3 -- tiny literal-loop unrolling. A `for` whose init, test and update are + * all integer literals runs a trip count this pass can compute exactly, so the + * loop becomes that many copies of its body with the induction variable + * substituted as a literal. The loop is gone, and with it the per-iteration + * compare, the increment, and -- on every backend that wraps an unprovable + * loop in the LOOP_MAX counter -- the cap machinery too. + * + * Bounds must be INTEGER literals, not merely literal. A fractional counter + * accumulates differently in f32 (GL, wasm) than in the f64 this pass would + * simulate it in, so `for (let t = 0; t < 1; t += 0.1)` could unroll to a + * different trip count than the backend would have run. Integers are exact in + * every format involved, which makes the simulated sequence the emitted one. + * + * Bodies are cloned into a BlockStatement each, so a body that declares a + * local declares it once per iteration in its own scope, exactly as the loop + * did. + */ +function unrollBlock(context, block) { + block.body = unrollList(context, block.body); +} + +function unrollList(context, list) { + const result = []; + for (let i = 0; i < list.length; i++) { + const replacement = unrollStatement(context, list[i]); + if (replacement === null) { + result.push(list[i]); + continue; + } + for (let j = 0; j < replacement.length; j++) result.push(replacement[j]); + } + return result; +} + +/** + * Descends before unrolling, so an inner loop is unrolled ONCE and the outer + * loop then clones the already-unrolled result -- rather than cloning the + * inner loop and unrolling every copy. + * @returns {Array|null} the statements replacing `statement`, or null to keep it + */ +function unrollStatement(context, statement) { + switch (statement.type) { + case 'BlockStatement': + unrollBlock(context, statement); + return null; + case 'IfStatement': + statement.consequent = unrollBranch(context, statement.consequent); + if (statement.alternate) statement.alternate = unrollBranch(context, statement.alternate); + return null; + case 'SwitchStatement': + for (let i = 0; i < statement.cases.length; i++) { + statement.cases[i].consequent = unrollList(context, statement.cases[i].consequent); + } + return null; + case 'WhileStatement': + case 'DoWhileStatement': + statement.body = unrollBranch(context, statement.body); + return null; + case 'ForStatement': + statement.body = unrollBranch(context, statement.body); + return unrollLoop(context, statement); + default: + return null; + } +} + +function unrollBranch(context, branch) { + if (!branch) return branch; + if (branch.type === 'BlockStatement') { + unrollBlock(context, branch); + return branch; + } + const replacement = unrollStatement(context, branch); + if (replacement === null) return branch; + return stampSynthetic({ type: 'BlockStatement', body: replacement }, branch); +} + +/** + * @returns {Array|null} one block per iteration, or null when this loop is not + * provably a tiny literal loop + */ +function unrollLoop(context, loop) { + if (!(context.loopUnrollLimit > 0)) return null; + if (loop.type !== 'ForStatement') return null; + const induction = inductionVariable(context, loop); + if (!induction) return null; + const values = tripValues(loop, induction, context.loopUnrollLimit); + if (!values) return null; + // A non-literal init (`let i = -2` is a UnaryExpression) falls outside the + // emitters' canonical-loop rule, so they wrap it in the LOOP_MAX safety + // form. Unrolling deletes that wrapper, which changes results whenever the + // trip count exceeds the cap (#4 of the build review) -- so unroll such a + // loop only when every iteration would have run anyway. + if (loop.init && loop.init.type === 'VariableDeclaration' && + loop.init.declarations[0].init.type !== 'Literal') { + // unset means the emitters' own default, not zero + const cap = context.functionNode.loopMaxIterations || 1000; + if (values.length > cap) return null; + } + const body = loop.body ? + (loop.body.type === 'BlockStatement' ? loop.body.body : [loop.body]) : []; + if (!bodyIsUnrollable(body, induction.name)) return null; + + // the cumulative guard: unrollStatement descends before it unrolls, so an + // inner loop is unrolled once and then CLONED by every outer iteration. + // Counting the copies this expansion adds against a running total is what + // keeps a 3-deep nest from emitting 8^3 bodies (#8). + const bodyNodes = countNodes(body); + const added = bodyNodes * (values.length - 1); + if (context.unrollAdded === undefined) context.unrollAdded = 0; + if (context.unrollAdded + added > UNROLL_MAX_ADDED_NODES) return null; + context.unrollAdded += added; + + const result = []; + for (let i = 0; i < values.length; i++) { + result.push(stampSynthetic({ + type: 'BlockStatement', + body: cloneNodes(context, body, induction.name, values[i]), + }, loop)); + } + return result; +} + +function countNodes(ast) { + let count = 0; + walk(ast, () => { count++; }); + return count; +} + +/** + * The counter a `for` header advances, when the header declares it itself. + * An init that ASSIGNS an existing variable is skipped: the loop leaves its + * final value behind for whatever follows, and unrolling would delete the + * variable's last write. + * @returns {{name: String, start: Number}|null} + */ +function inductionVariable(context, loop) { + const { init } = loop; + if (!init || init.type !== 'VariableDeclaration') return null; + if (init.declarations.length !== 1) return null; + const declaration = init.declarations[0]; + if (!declaration.id || declaration.id.type !== 'Identifier') return null; + const start = integerLiteral(declaration.init); + if (start === null) return null; + // `let`/`const` are scoped to the loop, so deleting the loop deletes the + // binding with it. `var` is function-scoped and outlives the loop, so it + // only unrolls when nothing outside the loop names it. + if (init.kind === 'var' && nameUsedOutside(context, loop, declaration.id.name)) return null; + return { name: declaration.id.name, start }; +} + +const comparators = { + '<': (value, bound) => value < bound, + '<=': (value, bound) => value <= bound, + '>': (value, bound) => value > bound, + '>=': (value, bound) => value >= bound, + '!==': (value, bound) => value !== bound, + '!=': (value, bound) => value !== bound, +}; + +/** + * @returns {Array|null} the induction variable's value on each + * iteration, or null when the loop does not terminate within the limit + */ +function tripValues(loop, induction, limit) { + const { test, update } = loop; + if (!test || test.type !== 'BinaryExpression') return null; + if (!test.left || test.left.type !== 'Identifier' || test.left.name !== induction.name) return null; + const bound = integerLiteral(test.right); + if (bound === null) return null; + const compare = comparators[test.operator]; + if (!compare) return null; + const step = inductionStep(update, induction.name); + if (step === null) return null; + + const values = []; + let value = induction.start; + while (compare(value, bound)) { + if (values.length >= limit) return null; + values.push(value); + value += step; + } + return values; +} + +/** + * @returns {Number|null} how much one iteration adds to the counter. Null for + * anything else -- including a zero step, which never terminates. + */ +function inductionStep(update, name) { + if (!update) return null; + if (update.type === 'UpdateExpression') { + if (!update.argument || update.argument.type !== 'Identifier' || update.argument.name !== name) return null; + return update.operator === '++' ? 1 : (update.operator === '--' ? -1 : null); + } + if (update.type !== 'AssignmentExpression') return null; + if (!update.left || update.left.type !== 'Identifier' || update.left.name !== name) return null; + switch (update.operator) { + case '+=': { + const step = integerLiteral(update.right); + return step === 0 ? null : step; + } + case '-=': { + const step = integerLiteral(update.right); + return step === null || step === 0 ? null : -step; + } + case '=': { + const { right } = update; + if (!right || right.type !== 'BinaryExpression') return null; + const leftIsCounter = right.left.type === 'Identifier' && right.left.name === name; + const rightIsCounter = right.right.type === 'Identifier' && right.right.name === name; + if (right.operator === '+') { + const step = leftIsCounter ? integerLiteral(right.right) : + (rightIsCounter ? integerLiteral(right.left) : null); + return step === 0 ? null : step; + } + if (right.operator === '-' && leftIsCounter) { + const step = integerLiteral(right.right); + return step === null || step === 0 ? null : -step; + } + return null; + } + default: + return null; + } +} + +function integerLiteral(ast) { + const value = literalNumber(ast); + return value === null || !Number.isInteger(value) ? null : value; +} + +/** + * @returns {Boolean} whether `name` appears anywhere in the function outside + * `loop` -- the question a function-scoped `var` counter raises. + */ +function nameUsedOutside(context, loop, name) { + let found = false; + const visit = node => { + if (found || !node || typeof node !== 'object') return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i]); + return; + } + if (typeof node.type !== 'string' || node === loop) return; + if (node.type === 'Identifier' && node.name === name) { + found = true; + return; + } + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') visit(child); + } + }; + visit(context.ast); + return found; +} + +/** + * @returns {Boolean} whether the body can be replayed with the counter frozen + * to a literal. Every rejection here is a shape where a copy would not mean + * what the iteration meant. + */ +function bodyIsUnrollable(body, name) { + let ok = true; + const reject = () => { + ok = false; + }; + const visit = (node, inBreakable, inContinuable) => { + if (!ok || !node || typeof node !== 'object') return; + if (Array.isArray(node)) { + for (let i = 0; i < node.length; i++) visit(node[i], inBreakable, inContinuable); + return; + } + if (typeof node.type !== 'string') return; + switch (node.type) { + case 'AssignmentExpression': + // a body that moves the counter decides its own trip count + if (node.left.type === 'Identifier' && node.left.name === name) return reject(); + break; + case 'UpdateExpression': + if (node.argument.type === 'Identifier' && node.argument.name === name) return reject(); + break; + case 'VariableDeclarator': + // an inner declaration SHADOWS the counter; substituting through it + // would rewrite reads of a different variable + if (node.id.type === 'Identifier' && node.id.name === name) return reject(); + break; + case 'BreakStatement': + // a break out of THIS loop stops iterations the unrolled form would + // still run; one bound to an inner loop or switch is untouched + if (node.label || !inBreakable) return reject(); + return; + case 'ContinueStatement': + if (node.label || !inContinuable) return reject(); + return; + case 'LabeledStatement': + return reject(); + case 'CallExpression': + // `Math.random()` is the one call whose VALUE depends on how many + // times it has already run: every backend lowers it to a generator + // carrying state between draws. The unrolled form draws exactly as + // often and in exactly the same order, so the sequence is preserved + // by construction -- but the GL lowering is + // `fract(sin(dot(...)) * 43758.5453)`, where a shader compiler + // reassociating one operand by a single ULP is a completely different + // number, and straight-line calls give it room a loop does not. + // Measured 4.5e-4 apart on ANGLE/Metal, so this shape skips. + if (isMathRandom(node)) return reject(); + break; + case 'FunctionDeclaration': + case 'FunctionExpression': + case 'ArrowFunctionExpression': + // nested functions are registered by AST identity, so cloning one + // would register the same helper under the same name several times + return reject(); + case 'ForStatement': + case 'WhileStatement': + case 'DoWhileStatement': + visit(node.init, true, true); + visit(node.test, true, true); + visit(node.update, true, true); + visit(node.body, true, true); + return; + case 'SwitchStatement': + visit(node.discriminant, inBreakable, inContinuable); + visit(node.cases, true, inContinuable); + return; + case 'MemberExpression': + visit(node.object, inBreakable, inContinuable); + if (node.computed) visit(node.property, inBreakable, inContinuable); + return; + } + for (const key in node) { + if (key === 'loc' || key === 'range' || key === 'parent') continue; + const child = node[key]; + if (child && typeof child === 'object') visit(child, inBreakable, inContinuable); + } + }; + visit(body, false, false); + return ok; +} + +/** + * The node acorn would have parsed for this number, which for a negative one + * is a unary minus over a positive literal rather than a literal holding a + * negative value. The emitters print a literal's value verbatim, so the + * negative form turns `2 - i` into `2--2` -- a decrement, and a syntax error + * in both JavaScript and GLSL. Substituting what the source form parses to + * keeps the unrolled body indistinguishable from a hand-written one. + */ +function numberNode(value, source) { + const literal = stampSynthetic({ + type: 'Literal', + value: Math.abs(value), + raw: `${ Math.abs(value) }`, + }, source); + if (value >= 0) return literal; + return stampSynthetic({ + type: 'UnaryExpression', + operator: '-', + prefix: true, + argument: literal, + }, source); +} + +function isMathRandom(ast) { + const { callee } = ast; + return Boolean(callee) && callee.type === 'MemberExpression' && !callee.computed && + callee.object.type === 'Identifier' && callee.object.name === 'Math' && + callee.property.name === 'random'; +} + +function cloneNodes(context, nodes, name, value) { + const result = new Array(nodes.length); + for (let i = 0; i < nodes.length; i++) result[i] = cloneNode(context, nodes[i], name, value); + return result; +} + +/** + * A deep copy with the induction variable replaced by its value for this + * iteration. Every copied node is stamped a fresh position: astKey and the + * literal-type cache are keyed by start/end, so two iterations sharing a + * position would share a type decision made for one of them. + * @param {String|null} name - the identifier to substitute, or null for a + * verbatim copy (a non-computed member's property, which is a field name) + */ +function cloneNode(context, node, name, value) { + if (!node || typeof node !== 'object') return node; + if (Array.isArray(node)) return cloneNodes(context, node, name, value); + if (typeof node.type !== 'string') return node; + if (name !== null && node.type === 'Identifier' && node.name === name) { + return numberNode(value, node); + } + const copy = {}; + const verbatimProperty = node.type === 'MemberExpression' && !node.computed; + for (const key in node) { + if (key === 'start' || key === 'end') continue; + if (key === 'loc' || key === 'range' || key === 'parent') { + copy[key] = node[key]; + continue; + } + copy[key] = cloneNode(context, node[key], verbatimProperty && key === 'property' ? null : name, value); + } + return stampSynthetic(copy, node); +} + +// -------------------------------------------------- T1: thread localization + +/** + * T1 -- coordinate localization, cpu only. Every other backend already holds + * the thread id in something local: wasm in mutable globals, GLSL and WGSL in + * locals seeded from a builtin. On cpu it is a property of a shared mutable + * object, re-read on every access -- but the generated cell loop that assigns + * it has the same value in its own counters, so the root kernel body can name + * those instead. + * + * Only the ROOT body is lexically inside that loop. Helpers and sub-kernels + * are emitted as sibling function declarations, where the counters are not in + * scope and `_this.thread` is the only way to ask. + * + * `this.constants.*` and `this.output.*` need no equivalent: the cpu backend + * already binds them to `constants_` and `outputX`/`outputY`/`outputZ`, + * hoisted above the cell loop, and both are in scope in helpers too. + * @param {FunctionNode} functionNode + * @param {String} name - 'x', 'y' or 'z' + * @returns {String|null} the expression to emit, or null to keep the property read + */ +function threadLocalName(functionNode, name) { + // OFF by default, and measured rather than reasoned: replacing the property + // read with the cell loop's own counter is neutral on small outputs but a + // real loss at scale -- 0.84x on a 3072x256 kernel with a 3072-trip inner + // loop (2048ms -> 2448ms), and worse in a full benchmark run. `_this.thread.x` + // is a monomorphic load on an object whose shape never changes, which V8 + // hoists out of an inner loop; a `let` counter from an enclosing loop it + // must re-read per iteration. The transform stays here, behind a flag, + // because a better emission (binding the counters once per cell, above the + // body) would likely win -- but it has to be measured before it ships on. + if (!functionNode.localizeThreadCoordinates) return null; + if (functionNode.optimizerDisabled || !functionNode.isRootKernel) return null; + const { output } = functionNode; + if (!output || !output.length) return null; + switch (name) { + case 'x': + return 'x'; + case 'y': + // a rank the output does not have has no counter; the loop preamble + // pins the coordinate to 0, which is what the literal says + return output.length > 1 ? 'y' : '0'; + case 'z': + return output.length > 2 ? 'z' : '0'; + default: + return null; + } +} + +module.exports = { + optimize, + buildInlinePlan, + threadLocalName +}; \ No newline at end of file diff --git a/src/backend/web-assembly/function-node.js b/src/backend/web-assembly/function-node.js index 5e75f6f2..8131d008 100644 --- a/src/backend/web-assembly/function-node.js +++ b/src/backend/web-assembly/function-node.js @@ -182,6 +182,21 @@ function scalarWasmType(type) { } class WebAssemblyFunctionNode extends FunctionNode { + /** + * Array reads compile to raw `load`s from linear memory: an out-of-range + * address traps rather than yielding a clamped texel, so a read moved to + * a place the un-optimized build never reaches is a new crash. Unlike cpu + * even a ONE-level read faults here, which is why canFault's + * two-subscript shortcut does not apply (see optimizer.readsFaultAtOneLevel). + */ + get readsCanFault() { + return true; + } + + get readsFaultAtOneLevel() { + return true; + } + constructor(source, settings) { super(source, settings); this.assembler = null; @@ -1089,6 +1104,16 @@ class WebAssemblyFunctionNode extends FunctionNode { this.coerce(this.expression(discriminant), 'i32'); this.em.localSet(dLocal); break; + case 'LiteralInteger': + // a number whose role was still open until it landed here -- a + // hand-written `switch (1)`, or a loop counter the unroller replaced + // with its value. Every case test is compared as an integer, so the + // discriminant is one. + dIsInt = true; + dLocal = this.em.addLocal('i32'); + this.castLiteralToInteger(discriminant); + this.em.localSet(dLocal); + break; default: throw this.astErrorOutput(`Unhandled switch discriminant type "${ type }"`, ast); } @@ -3372,6 +3397,12 @@ class WebAssemblyFunctionNode extends FunctionNode { this.coerce(this.expression(discriminant), 'i32'); em.localSet(dLocal); break; + case 'LiteralInteger': + dIsInt = true; + dLocal = em.addLocal('i32'); + this.castLiteralToInteger(discriminant); + em.localSet(dLocal); + break; default: throw this.astErrorOutput(`Unhandled switch discriminant type "${ type }"`, ast); } @@ -3417,6 +3448,7 @@ class WebAssemblyFunctionNode extends FunctionNode { em.localSet(dLocal); break; case 'Integer': + case 'LiteralInteger': dIsInt = true; dLocal = em.addLocal('v128'); this.vCoerce(this.vexpr(discriminant), 'vi32'); diff --git a/src/backend/web-assembly/kernel.js b/src/backend/web-assembly/kernel.js index 3ce06a01..dcaf0eb5 100644 --- a/src/backend/web-assembly/kernel.js +++ b/src/backend/web-assembly/kernel.js @@ -269,12 +269,23 @@ class WebAssemblyKernel extends Kernel { while (threadDim.length < 3) { threadDim.push(1); } - if (!this.translateSource()) { + // the bytecode is emitted by _instantiate, not by translateSource, so the + // optimizer guard has to span both -- a rebuild with optimizations off + // has to redo the analysis pass that produced the function nodes + let unsupportedReturnType = false; + this.buildWithOptimizer(() => { + if (!this.translateSource()) { + unsupportedReturnType = true; + return; + } + unsupportedReturnType = false; + this.buildSignature(arguments); + this._instantiate(this._entryKey(arguments), arguments); + }); + if (unsupportedReturnType) { return this.requestFallback(arguments, `return type ${ this.returnType } is not supported on the webasm backend`); } - this.buildSignature(arguments); - this._instantiate(this._entryKey(arguments), arguments); this.built = true; } diff --git a/src/backend/web-gl/function-node.js b/src/backend/web-gl/function-node.js index 024993b4..1d2cb5c0 100644 --- a/src/backend/web-gl/function-node.js +++ b/src/backend/web-gl/function-node.js @@ -288,7 +288,7 @@ class WebGLFunctionNode extends FunctionNode { // truncates, and `this.thread.x / 64` comes out 0. Only the accuracy // wrapper is conditional; the casting is not. if (ast.operator === '/') { - const wrap = this.fixIntegerDivisionAccuracy; + const wrap = this.fixIntegerDivisionAccuracy && !this.divisionIsProvablyFractional(ast); retArr.push(wrap ? 'divWithIntCheck(' : '('); this.pushState('building-float'); switch (this.getType(ast.left)) { @@ -467,6 +467,22 @@ class WebGLFunctionNode extends FunctionNode { return retArr; } + /** + * @desc Whether `divWithIntCheck` would provably take its fallback path, so + * the site can emit the plain operator instead of the emitted helper. The + * helper only does anything when BOTH operands are whole numbers -- it + * recovers the exact quotient of an integer division on hardware whose + * integer divide is inaccurate -- and returns `x / y` otherwise. A literal + * operand with a fraction in it settles that statically, so the call, the + * two floor comparisons and the branch all come out, on exactly the devices + * that turn the fix on. + * @param {Object} ast - a BinaryExpression with operator '/' + * @returns {Boolean} + */ + divisionIsProvablyFractional(ast) { + return isFractionalLiteral(ast.left) || isFractionalLiteral(ast.right); + } + checkAndUpconvertOperator(ast, retArr) { const bitwiseResult = this.checkAndUpconvertBitwiseOperators(ast, retArr); if (bitwiseResult) { @@ -1678,7 +1694,13 @@ class WebGLFunctionNode extends FunctionNode { throw this.astErrorOutput('Invalid switch statement', ast); } const { discriminant, cases } = ast; - const type = this.getType(discriminant); + // a discriminant whose role was still open until it landed here -- a + // hand-written `switch (1)`, or a loop counter the unroller replaced with + // its value -- is decided by the case tests, which compare as integers. + // Without this the declaration below was skipped entirely and every + // comparison referred to a variable that was never declared. + const literalDiscriminant = this.getType(discriminant) === 'LiteralInteger'; + const type = literalDiscriminant ? 'Integer' : this.getType(discriminant); const varName = `switchDiscriminant${this.astKey(ast, '_')}`; switch (type) { case 'Float': @@ -1689,7 +1711,11 @@ class WebGLFunctionNode extends FunctionNode { break; case 'Integer': retArr.push(`int ${varName} = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) { + this.castLiteralToInteger(discriminant, retArr); + } else { + this.astGeneric(discriminant, retArr); + } retArr.push(';\n'); break; } @@ -2203,7 +2229,14 @@ class WebGLFunctionNode extends FunctionNode { retArr.push(')'); continue; } else if (targetType === 'Integer') { + // the parameter's declared type IS the context. An Integer-typed + // expression made only of numbers -- `f(1 + 1)`, or a loop + // counter the unroller replaced with its value -- has nothing + // else to tell it which way to emit, and without being told it + // builds as float and misses the `int` overload. + this.pushState('building-integer'); this.astGeneric(argument, retArr); + this.popState('building-integer'); continue; } break; @@ -2325,6 +2358,16 @@ class WebGLFunctionNode extends FunctionNode { case 'LiteralInteger': this.castLiteralToInteger(property, result); break; + case 'Integer': + // an index is an integer context, and saying so is what an + // Integer-typed subscript made only of numbers needs to hear: + // `a[1 + 2]`, or `a[i + 2]` after the unroller replaced the counter + // with its value, otherwise builds as float and misses every sampler + // overload + this.pushState('building-integer'); + this.astGeneric(property, result); + this.popState('building-integer'); + break; default: this.astGeneric(property, result); } @@ -2525,6 +2568,20 @@ const operatorMap = { '!==': '!=' }; +/** + * @param {Object} ast + * @returns {Boolean} whether an expression is a numeric literal that is not a + * whole number -- including a signed one, which parses as a unary minus over a + * positive literal + */ +function isFractionalLiteral(ast) { + if (!ast) return false; + if (ast.type === 'UnaryExpression' && (ast.operator === '-' || ast.operator === '+')) { + return isFractionalLiteral(ast.argument); + } + return ast.type === 'Literal' && typeof ast.value === 'number' && !Number.isInteger(ast.value); +} + module.exports = { WebGLFunctionNode }; \ No newline at end of file diff --git a/src/backend/web-gl/kernel.js b/src/backend/web-gl/kernel.js index ba96f132..b0175642 100644 --- a/src/backend/web-gl/kernel.js +++ b/src/backend/web-gl/kernel.js @@ -205,6 +205,27 @@ class WebGLKernel extends GLKernel { return this.canvas.getContext('webgl', settings) || this.canvas.getContext('experimental-webgl', settings); } + /** + * @desc The text a plugin's `functionMatch` is tested against. A plugin + * substitutes a GLSL implementation for a JavaScript call (`Math.random()` + * for `nrand`), so it has to be selected by what the whole PROGRAM says, + * not just the kernel: a helper added with addFunction is compiled into the + * same shader, and matching only the kernel left its `Math.random()` calling + * a `random()` that no shader ever declared. + * @return {String|null} null when the source is a rehydrated AST rather than + * text, where pluginNames is the selector instead + */ + pluginMatchSource() { + if (typeof this.source !== 'string') return null; + if (!this.functions || this.functions.length < 1) return this.source; + const sources = [this.source]; + for (let i = 0; i < this.functions.length; i++) { + const source = this.functions[i] ? this.functions[i].source : null; + if (typeof source === 'string') sources.push(source); + } + return sources.join('\n'); + } + /** * * @param {IDirectKernelSettings} settings @@ -213,7 +234,7 @@ class WebGLKernel extends GLKernel { initPlugins(settings) { // default plugins const pluginsToUse = []; - const { source } = this; + const source = this.pluginMatchSource(); if (typeof source === 'string') { for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i]; @@ -221,7 +242,7 @@ class WebGLKernel extends GLKernel { pluginsToUse.push(plugin); } } - } else if (typeof source === 'object') { + } else if (typeof this.source === 'object') { // `source` is from object, json if (settings.pluginNames) { //TODO: in context of JSON support, pluginNames may not exist here for (let i = 0; i < plugins.length; i++) { @@ -507,7 +528,7 @@ class WebGLKernel extends GLKernel { this.setupArguments(arguments); if (this.fallbackRequested) return; this.updateMaxTexSize(); - this.translateSource(); + this.buildWithOptimizer(() => this.translateSource()); const failureResult = this.pickRenderStrategy(arguments); if (failureResult) { return failureResult; @@ -1059,7 +1080,9 @@ class WebGLKernel extends GLKernel { _getPluginsString() { if (!this.plugins) return '\n'; - return this.plugins.map(plugin => plugin.source && this.source.match(plugin.functionMatch) ? plugin.source : '').join('\n'); + const source = this.pluginMatchSource(); + if (typeof source !== 'string') return '\n'; + return this.plugins.map(plugin => plugin.source && source.match(plugin.functionMatch) ? plugin.source : '').join('\n'); } /** diff --git a/src/backend/web-gpu/function-node.js b/src/backend/web-gpu/function-node.js index 66ef2ee2..e313d0ea 100644 --- a/src/backend/web-gpu/function-node.js +++ b/src/backend/web-gpu/function-node.js @@ -1009,7 +1009,11 @@ class WGSLFunctionNode extends FunctionNode { throw this.astErrorOutput('Invalid switch statement', ast); } const { discriminant, cases } = ast; - const type = this.getType(discriminant); + // a discriminant whose role was still open until it landed here -- a + // hand-written `switch (1)`, or a loop counter the unroller replaced with + // its value -- is decided by the case tests, which compare as integers + const literalDiscriminant = this.getType(discriminant) === 'LiteralInteger'; + const type = literalDiscriminant ? 'Integer' : this.getType(discriminant); const varName = `switchDiscriminant${ this.astKey(ast, '_') }`; switch (type) { case 'Float': @@ -1020,7 +1024,11 @@ class WGSLFunctionNode extends FunctionNode { break; case 'Integer': retArr.push(`var ${ varName } : i32 = `); - this.astGeneric(discriminant, retArr); + if (literalDiscriminant) { + this.castLiteralToInteger(discriminant, retArr); + } else { + this.astGeneric(discriminant, retArr); + } retArr.push(';\n'); break; default: @@ -1423,7 +1431,13 @@ class WGSLFunctionNode extends FunctionNode { retArr.push(')'); continue; } else if (targetType === 'Integer') { + // the parameter's declared type IS the context. An Integer-typed + // expression made only of numbers -- `f(1 + 1)`, or a loop + // counter the unroller replaced with its value -- has nothing + // else to tell it which way to emit. + this.pushState('building-integer'); this.astGeneric(argument, retArr); + this.popState('building-integer'); continue; } break; diff --git a/src/backend/web-gpu/kernel.js b/src/backend/web-gpu/kernel.js index dbafb294..f22da60b 100644 --- a/src/backend/web-gpu/kernel.js +++ b/src/backend/web-gpu/kernel.js @@ -268,9 +268,11 @@ class WebGPUKernel extends Kernel { while (threadDim.length < 3) { threadDim.push(1); } - this.translateSource(); - this.paramsLayout = this.computeParamsLayout(); - this.compiledSource = this.assembleWGSL(); + this.buildWithOptimizer(() => { + this.translateSource(); + this.paramsLayout = this.computeParamsLayout(); + this.compiledSource = this.assembleWGSL(); + }); if (this.debug) { console.log('WGSL Shader Output:'); console.log(this.compiledSource); diff --git a/src/gpu.js b/src/gpu.js index 5476dcd8..3cb53063 100644 --- a/src/gpu.js +++ b/src/gpu.js @@ -326,6 +326,8 @@ class GPU { injectedNative: kernelRun.injectedNative, subKernels: kernelRun.subKernels, strictIntegers: kernelRun.strictIntegers, + _optimizerDisabled: kernelRun._optimizerDisabled, + loopUnrollLimit: kernelRun.loopUnrollLimit, randomSeed: kernelRun.randomSeed, debug: kernelRun.debug, asyncMode: kernelRun.asyncMode, @@ -413,6 +415,8 @@ class GPU { injectedNative: _kernel.injectedNative, subKernels: _kernel.subKernels, strictIntegers: _kernel.strictIntegers, + _optimizerDisabled: _kernel._optimizerDisabled, + loopUnrollLimit: _kernel.loopUnrollLimit, randomSeed: _kernel.randomSeed, debug: _kernel.debug, asyncMode: _kernel.asyncMode, @@ -526,6 +530,8 @@ class GPU { precision: currentKernel.precision, tactic: currentKernel.tactic, strictIntegers: currentKernel.strictIntegers, + _optimizerDisabled: currentKernel._optimizerDisabled, + loopUnrollLimit: currentKernel.loopUnrollLimit, fixIntegerDivisionAccuracy: currentKernel.fixIntegerDivisionAccuracy, subKernels: currentKernel.subKernels, graphical: currentKernel.graphical, diff --git a/src/index.d.ts b/src/index.d.ts index d2b2a7fd..c2fd10cc 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -177,6 +177,7 @@ export class Kernel { debug: boolean; graphical: boolean; loopMaxIterations: number; + loopUnrollLimit: number; constants: IConstants; canvas: any; context: WebGLRenderingContext | any; @@ -214,6 +215,7 @@ export class Kernel { setDebug(flag: boolean): this; setGraphical(flag: boolean): this; setLoopMaxIterations(flag: number): this; + setLoopUnrollLimit(flag: number): this; setConstants(flag: IConstants): this; setConstants(flag: T & IConstants): this; setConstantTypes(flag: IKernelValueTypes): this; @@ -371,6 +373,8 @@ export interface IKernelSettings { nativeFunctions?: IGPUNativeFunction[], strictIntegers?: boolean; randomSeed?: number; + /** largest trip count a loop with literal bounds is unrolled at; 0 leaves every loop as written. Default 8 */ + loopUnrollLimit?: number; } export interface IDirectKernelSettings extends IKernelSettings { @@ -597,6 +601,7 @@ export interface IFunctionSettings { output?: number[]; loopMaxIterations?: number; + loopUnrollLimit?: number; returnType?: string; isRootKernel?: boolean; isSubKernel?: boolean; diff --git a/src/pipeline.js b/src/pipeline.js index dece5dae..a332bc7c 100644 --- a/src/pipeline.js +++ b/src/pipeline.js @@ -635,7 +635,7 @@ class Pipeline { // (texture in the ping-pong seat, plain array from a pipeline arg) dynamicArguments: true, }, overrides || {}); - const optional = ['constants', 'constantTypes', 'precision', 'loopMaxIterations', 'strictIntegers', 'fixIntegerDivisionAccuracy', 'optimizeFloatMemory', 'tactic', 'functions', 'nativeFunctions', 'injectedNative', 'debug', 'randomSeed', 'returnType']; + const optional = ['constants', 'constantTypes', 'precision', 'loopMaxIterations', 'strictIntegers', 'fixIntegerDivisionAccuracy', 'optimizeFloatMemory', 'tactic', 'functions', 'nativeFunctions', 'injectedNative', 'debug', 'randomSeed', 'returnType', 'loopUnrollLimit', '_optimizerDisabled', '_inliningDisabled']; // types the USER declared pin the clone exactly as they pin the kernel; // types inferred by a build must not -- the clone re-infers per plan // seat (texture in the ping-pong seat, plain array from a pipeline arg) diff --git a/test/all.html b/test/all.html index aa7c2620..dc88da02 100644 --- a/test/all.html +++ b/test/all.html @@ -307,6 +307,10 @@ + + + + diff --git a/test/features/optimizer/hoisting.js b/test/features/optimizer/hoisting.js new file mode 100644 index 00000000..cdbcbe50 --- /dev/null +++ b/test/features/optimizer/hoisting.js @@ -0,0 +1,256 @@ +const { assert, skip, test, module: describe } = require('qunit'); +const { GPU, FunctionNode } = require('../../../src'); + +describe('features: optimizer hoisting'); + +// Parity proves the optimizer changes no answer. These prove it changes the +// EMISSION -- in both directions, because a pass that quietly does nothing +// also passes every parity row. Each shape is asserted against the text the +// backend actually compiles: the cpu backend's generated JavaScript and the +// GL backends' generated GLSL. + +const GL_MODE = GPU.isHeadlessGLSupported ? 'headlessgl' : (GPU.isWebGLSupported ? 'webgl' : null); + +// Every shape here is about hoisting, so the unroller is off throughout: with +// it on, the loops these kernels hoist out of are gone by the time the text is +// read, and the file would be asserting T3's behavior under H's name. +const H_ONLY = { output: [4], loopUnrollLimit: 0 }; + +/** + * The emitted source, plus whether the build stayed optimized. A bail row + * asserts that the optimized text equals the un-optimized text, and a + * build-time throw degrades to exactly that text (#868) -- so without the + * second half, a bail that broke badly enough to crash the pass would still + * read as a clean skip. + */ +function cpuBuild(kernelSource, settings, args) { + const gpu = new GPU({ mode: 'cpu' }); + try { + const kernel = gpu.createKernel(kernelSource, Object.assign({}, H_ONLY, settings)); + kernel.apply(null, args || [[1, 2, 3, 4]]); + return { source: kernel.kernel.kernelString, optimized: !kernel.kernel._optimizerDisabled }; + } finally { + gpu.destroy(); + } +} + +function cpuSource(kernelSource, settings, args) { + return cpuBuild(kernelSource, settings, args).source; +} + +function glSource(kernelSource, settings, args) { + const gpu = new GPU({ mode: GL_MODE }); + try { + const kernel = gpu.createKernel(kernelSource, Object.assign({}, H_ONLY, settings)); + kernel.apply(null, args || [[1, 2, 3, 4]]); + return kernel.kernel.translatedSource; + } finally { + gpu.destroy(); + } +} + +// The user's own loop, not the cell loop the cpu backend wraps every kernel +// in: its counter carries the emitters' user namespace. +const userLoop = /for \((let|int) user_/; + +function afterFirstLoop(source) { + const at = source.search(userLoop); + return at === -1 ? '' : source.slice(at); +} + +function beforeFirstLoop(source) { + const at = source.search(userLoop); + return at === -1 ? source : source.slice(0, at); +} + +const HOT_LOOP = function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return s; +}; + +test('cpu: an invariant read leaves the loop body', () => { + const optimized = cpuSource(HOT_LOOP); + const disabled = cpuSource(HOT_LOOP, { _optimizerDisabled: true }); + + assert.ok(/const user_optHoist0\s*=\s*user_a\[(?:x|_this\.thread\.x)\]/.test(beforeFirstLoop(optimized)), + 'optimized: the read is a const ahead of the loop'); + assert.notOk(/user_a\[/.test(afterFirstLoop(optimized)), + 'optimized: no array read is left inside the loop'); + + assert.notOk(/optHoist/.test(disabled), 'disabled: nothing is hoisted'); + assert.ok(/user_a\[_this\.thread\.x\]/.test(afterFirstLoop(disabled)), + 'disabled: the read stays inside the loop'); +}); + +(GL_MODE ? test : skip)('gl: an invariant read leaves the loop body', () => { + const optimized = glSource(HOT_LOOP); + const disabled = glSource(HOT_LOOP, { _optimizerDisabled: true }); + + assert.ok(/float user_optHoist0=get/.test(beforeFirstLoop(optimized)), + 'optimized: the texture read is a float ahead of the loop'); + assert.notOk(/get\w*\(user_a/.test(afterFirstLoop(optimized)), + 'optimized: no texture read is left inside the loop'); + assert.ok(/get\w*\(user_a/.test(afterFirstLoop(disabled)), + 'disabled: the texture read stays inside the loop'); +}); + +test('cpu: two spellings of the same read share one const', () => { + const source = cpuSource(function (a) { + let s = 0; + for (let i = 0; i < 4; i++) { + s += a[this.thread.x] * (i + 1); + s += a[this.thread.x] * 2; + } + return s; + }); + assert.equal((source.match(/const user_optHoist/g) || []).length, 1, + 'one hoisted const for both reads'); + assert.equal((source.match(/user_optHoist0/g) || []).length, 3, + 'declared once, referenced twice'); +}); + +test('cpu: a read invariant to a whole nest leaves both loops', () => { + const source = cpuSource(function (a) { + let s = 0; + for (let y = 0; y < 3; y++) { + for (let x = 0; x < 3; x++) { + s += a[1][2] + y * 0.5 + x * 0.25; + } + } + return s; + }, {}, [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]); + assert.ok(/const user_optHoist0\s*=\s*user_a\[1\]\[2\]/.test(beforeFirstLoop(source)), + 'the read sits ahead of the OUTER loop'); + assert.equal((source.match(/user_a\[1\]\[2\]/g) || []).length, 1, + 'and appears exactly once in the whole kernel'); +}); + +// Every bail below asserts the strongest thing available: the optimized text +// is the un-optimized text, character for character. A bail rule that stops +// working shows up here as a diff, wherever in the pass it broke. +// +// None of them reads `this.thread`, and that is deliberate rather than +// incidental: coordinate localization (T1) rewrites those reads on cpu, so a +// kernel containing one cannot be compared character for character against a +// build with the whole optimizer off. Subscripts come from an argument +// instead, which hoists on exactly the same terms. +const BAILS = [ + { + name: 'a read under a conditional', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 8; i++) { + if (i > n) s += a[n]; + } + return s; + }, + args: [[1, 2, 3, 4], 2], + }, + { + name: 'a subscript assigned in the body', + kernel: function (a) { + let k = 0; + let s = 0; + for (let i = 0; i < 4; i++) { + s += a[k]; + k = (k + 1) % 4; + } + return s; + }, + }, + { + name: 'a subscript containing a call', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[Math.round(n * 0.5)]; + return s; + }, + args: [[1, 2, 3, 4], 2], + }, + { + name: 'a reassigned array argument', + kernel: function (b, a, n) { + a = b; + let s = 0; + for (let i = 0; i < 4; i++) s += a[n]; + return s; + }, + args: [[1, 2, 3, 4], [4, 3, 2, 1], 2], + }, + { + name: 'a read after a conditional break', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 8; i++) { + if (i > n) break; + s += a[n]; + } + return s; + }, + args: [[1, 2, 3, 4], 2], + }, + { + name: 'a read after a conditional return', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 8; i++) { + if (i > 6) return s; + s += a[n]; + } + return s; + }, + args: [[1, 2, 3, 4], 2], + }, + { + name: 'a local array, which the kernel may write', + kernel: function (a) { + const v = [a[0], a[1], a[2]]; + let s = 0; + for (let i = 0; i < 4; i++) s += v[1]; + return s; + }, + }, +]; + +for (let i = 0; i < BAILS.length; i++) { + const bail = BAILS[i]; + test(`cpu bail: ${ bail.name }`, () => { + const settings = { loopMaxIterations: 20 }; + const built = cpuBuild(bail.kernel, settings, bail.args); + const disabled = cpuSource(bail.kernel, Object.assign({ _optimizerDisabled: true }, settings), bail.args); + assert.ok(built.optimized, `${ bail.name }: the optimized build stayed optimized`); + assert.notOk(/optHoist/.test(built.source), `${ bail.name }: nothing hoisted`); + assert.equal(built.source, disabled, `${ bail.name }: emission is unchanged`); + }); +} + +// The #868 contract: a build-time throw from the optimizer degrades to an +// un-optimized build rather than taking the kernel down with it. +test('a throw from the optimizer rebuilds with it off', () => { + const original = FunctionNode.prototype.optimizeAST; + const warnings = []; + const originalWarn = console.warn; + console.warn = message => warnings.push(String(message)); + // throws only while optimizing, so the rebuild -- which runs with + // optimizerDisabled set -- gets through + FunctionNode.prototype.optimizeAST = function (ast) { + if (!this.optimizerDisabled) throw new Error('deliberate optimizer failure'); + return ast; + }; + const gpu = new GPU({ mode: 'cpu' }); + try { + const kernel = gpu.createKernel(HOT_LOOP, { output: [4] }); + assert.deepEqual(Array.from(kernel([1, 2, 3, 4])), [10, 20, 30, 40], + 'the kernel still computes'); + assert.ok(kernel.kernel._optimizerDisabled, 'the rebuild turned the optimizer off'); + assert.ok(/deliberate optimizer failure/.test(kernel.kernel.fallbackReason || ''), + `fallbackReason names the cause: ${ kernel.kernel.fallbackReason }`); + assert.ok(warnings.some(message => /compiler optimizations/.test(message)), + 'the degradation is warned about'); + } finally { + console.warn = originalWarn; + FunctionNode.prototype.optimizeAST = original; + gpu.destroy(); + } +}); diff --git a/test/features/optimizer/inlining.js b/test/features/optimizer/inlining.js new file mode 100644 index 00000000..04206913 --- /dev/null +++ b/test/features/optimizer/inlining.js @@ -0,0 +1,462 @@ +const { assert, skip, test, module: describe } = require('qunit'); +const { GPU, FunctionBuilder, FunctionNode } = require('../../../src'); + +describe('features: optimizer inlining'); + +// T2's emission tests, both directions. Parity proves inlining changes no +// answer; these prove it changes the emitted program, and that every shape the +// plan refuses to inline emits EXACTLY what the un-optimized build emits -- +// character for character, so a "bail" that quietly rewrote something still +// fails here. + +const GL_MODE = GPU.isHeadlessGLSupported ? 'headlessgl' : (GPU.isWebGLSupported ? 'webgl' : null); + +// the unroller is off throughout: an inlined body full of tiny loops is T3's +// subject, and with it on this file would be asserting T3's behavior under +// T2's name +const T2_ONLY = { output: [4], loopUnrollLimit: 0 }; + +function build(mode, kernelSource, settings, args, extra) { + const gpu = new GPU({ mode }); + try { + const kernel = gpu.createKernel(kernelSource, + Object.assign({}, T2_ONLY, settings, extra || {})); + kernel.apply(null, args || [[1, 2, 3, 4]]); + const inner = kernel.kernel; + return { + source: mode === 'cpu' ? inner.kernelString : inner.translatedSource, + optimized: !inner._optimizerDisabled, + reason: inner.fallbackReason, + }; + } finally { + gpu.destroy(); + } +} + +// cpu ships with T2 off (V8 inlines small helpers better than we do), but +// the inliner's MECHANICS -- parameter binding, renaming, early-return +// folding, evaluation order -- are backend-independent and far easiest to +// read in emitted JavaScript, so these rows opt back in +function cpuSource(kernelSource, settings, args) { + return build('cpu', kernelSource, Object.assign({ _inliningDisabled: false }, settings), args).source; +} + +/** + * A shape T2 must leave alone emits the same text either way. The optimized + * build is also asserted to have STAYED optimized: a build-time throw degrades + * to the un-optimized text (#868), which would otherwise read as a clean skip. + */ +function assertUntouched(mode, label, kernelSource, settings, args) { + const optimized = build(mode, kernelSource, settings, args); + // compared against inlining OFF rather than the whole pass off: these + // kernels have reads for H to hoist too, and only T2's share is on trial + const disabled = build(mode, kernelSource, settings, args, { _inliningDisabled: true }); + assert.ok(optimized.optimized, `${ label }: the build stayed optimized (${ optimized.reason || 'no fallback' })`); + assert.equal(optimized.source, disabled.source, `${ label }: emission is untouched`); +} + +function poly(x) { + return x * x * 0.5 + x * 0.25 - 0.125; +} + +function scale(x, by) { + return poly(x) * by; +} + +function outer(x) { + return scale(x, 2) + 1; +} + +// --------------------------------------------------------------- it inlines + +test('cpu: the helper definition and its call site both go', () => { + const source = cpuSource(function (a) { + return poly(a[this.thread.x]); + }, { functions: [poly] }); + assert.notOk(/function poly\(/.test(source), 'no definition emitted'); + assert.notOk(/[^_]poly\(/.test(source), 'no call site emitted'); + assert.ok(/user_optIn0_x/.test(source), 'the parameter became a binding'); +}); + +test('cpu: a chain three deep expands to arithmetic', () => { + const source = cpuSource(function (a) { + return outer(a[this.thread.x]); + }, { functions: [poly, scale, outer] }); + for (const name of ['poly', 'scale', 'outer']) { + assert.notOk(new RegExp(`function ${ name }\\(`).test(source), `${ name } definition gone`); + } + assert.ok(/\*2\)\+1\)/.test(source.replace(/\s/g, '')), + 'the outermost helper\'s arithmetic is inline'); +}); + +test('cpu: an argument evaluated once, in source order, per parameter', () => { + const source = cpuSource(function (a) { + return twoArg(a[this.thread.x] + 1, a[this.thread.x] + 2); + }, { + functions: [function twoArg(p, q) { + return p * q + p * 2 + q * 3; + }], + }); + const bindings = source.match(/const user_optIn\d+_[pq]=/g) || []; + assert.equal(bindings.length, 2, 'one binding per parameter'); + assert.ok(source.indexOf('_p=') < source.indexOf('_q='), 'bound in source order'); + assert.equal((source.match(/\+1\)/g) || []).length, 1, 'the first argument is evaluated once'); +}); + +test('cpu: an atom argument is written in place rather than bound', () => { + const source = cpuSource(function (a) { + return poly(a[this.thread.x]) + shift(this.thread.x); + }, { + functions: [poly, function shift(k) { + return k * 2 + k * 3; + }], + }); + assert.notOk(/optIn\d+_k/.test(source), 'no binding for a coordinate argument'); + assert.ok(/\((?:x|_this\.thread\.x)\*2\)\+\((?:x|_this\.thread\.x)\*3\)/.test(source.replace(/\s/g, '')), 'the coordinate is read in place'); +}); + +test('cpu: a helper local is renamed out of the way of a kernel local', () => { + const source = cpuSource(function (a) { + const t = a[this.thread.x]; + return shadowy(t) + t; + }, { + functions: [function shadowy(v) { + const t = v * 3; + return t * t; + }], + }); + assert.ok(/const user_optIn\d+_t=/.test(source), 'the helper local took a fresh name'); + assert.ok(/constuser_t=user_a\[(?:x|_this\.thread\.x)\]/.test(source.replace(/\s/g, '')), "the kernel's own `t` kept its name"); +}); + +test('cpu: a reassigned parameter binds mutably', () => { + const source = cpuSource(function (a) { + return bump(a[this.thread.x]); + }, { + functions: [function bump(v) { + v = v + 1; + return v * v; + }], + }); + assert.ok(/let user_optIn\d+_v=/.test(source), 'bound with let, not const'); + assert.notOk(/const user_optIn\d+_v=/.test(source), 'and not both'); +}); + +test('cpu: an early return folds to a conditional, not a call', () => { + const source = cpuSource(function (a) { + return clampish(a[this.thread.x]); + }, { + functions: [function clampish(v) { + if (v < 0) return 0; + return v * 2; + }], + }); + assert.notOk(/function clampish/.test(source), 'the helper is gone'); + assert.ok(/\?0:/.test(source.replace(/\s/g, '')), 'the early return became a conditional'); +}); + +test('cpu: a void helper leaves its statements and no call', () => { + const source = cpuSource(function (a) { + record(a[this.thread.x]); + return a[this.thread.x] * 2; + }, { + functions: [function record(v) { + const unused = v * 2; + }], + }); + assert.notOk(/function record/.test(source), 'the helper is gone'); + assert.ok(/const user_optIn\d+_unused=/.test(source), 'its statements stayed'); +}); + +(GL_MODE ? test : skip)('gl: the helper definition and its call site both go', () => { + const source = build(GL_MODE, function (a) { + return poly(a[this.thread.x]); + }, { functions: [poly] }).source; + assert.notOk(/float poly\(/.test(source), 'no GLSL definition emitted'); + assert.notOk(/[^_a-zA-Z]poly\(/.test(source), 'no call site emitted'); +}); + +test('webasm: an array argument to a helper compiles once it is inlined', () => { + if (!GPU.isWebAssemblySupported) { + assert.ok(true, 'webasm unsupported here'); + return; + } + // the backend rejects array parameters outright; inlining leaves no + // parameter to reject, which is a shape T2 makes buildable rather than + // merely faster + const source = function (a) { + return element(a, this.thread.x) * 2; + }; + const settings = { + output: [4], + functions: [function element(m, k) { + return m[k]; + }], + }; + const gpu = new GPU({ mode: 'webasm' }); + try { + const optimized = gpu.createKernel(source, settings); + assert.deepEqual(Array.from(optimized([1, 2, 3, 4])), [2, 4, 6, 8], 'the optimized build runs'); + assert.throws(() => { + gpu.createKernel(source, Object.assign({ _optimizerDisabled: true }, settings))([1, 2, 3, 4]); + }, /array arguments to helper functions/, 'the un-optimized build still cannot'); + } finally { + gpu.destroy(); + } +}); + +// ---------------------------------------------------------------- it bails + +test('cpu bail: a call in a conditional operand', () => { + assertUntouched('cpu', 'ternary branch', function (a) { + return this.thread.x > 1 ? poly(a[this.thread.x]) : 0; + }, { functions: [poly] }); +}); + +test('cpu bail: a call in a loop test', () => { + assertUntouched('cpu', 'loop test', function (a) { + let s = 0; + for (let i = 0; i < poly(a[0]) + 4; i++) s += a[this.thread.x]; + return s; + }, { functions: [poly] }); +}); + +test('cpu bail: a call after an update in the same statement', () => { + assertUntouched('cpu', 'update before the call', function (a) { + let k = 0; + let s = 0; + s += a[k++] + poly(a[this.thread.x]); + return s; + }, { functions: [poly] }); +}); + +test('cpu bail: a call after Math.random in the same statement', () => { + assertUntouched('cpu', 'draw before the call', function (a) { + return Math.random() * 0 + poly(a[this.thread.x]); + }, { functions: [poly] }); +}); + +test('cpu bail: an unhoistable site blocks its helper everywhere', () => { + // the first call is in a perfectly hoistable position; the second is not. + // Inlining only the first would leave the helper emitted with one call site + // fewer, and gpu.js fixes a helper's parameter types from whichever site the + // emitter reaches first -- so a partial inline can change what the SURVIVING + // call coerces its argument to. + assertUntouched('cpu', 'one clean site, one dirty', function (a) { + let k = 0; + const safe = poly(a[this.thread.x]); + const dirty = a[k++] * poly(a[0]); + return safe + dirty + k; + }, { functions: [poly] }); +}); + +test('cpu bail: an early return whose branches draw', () => { + // folding this to a conditional is safe where `?:` is lazy, but WGSL's + // `select` evaluates both operands, so the untaken branch would advance that + // invocation's PCG stream + assertUntouched('cpu', 'draw in a folded branch', function (a) { + return maybeDraw(a[this.thread.x]); + }, { + randomSeed: 5, + functions: [function maybeDraw(v) { + if (v < 0) return Math.random(); + return v * 2; + }], + }); +}); + +test('cpu bail: one blocked site blocks the helper everywhere', () => { + // the helper still gets emitted, so its parameter types are still fixed by + // whichever call site the emitter reaches first -- which is only the same + // decision the un-optimized build makes if NO site was removed + assertUntouched('cpu', 'mixed sites', function (a) { + const safe = poly(a[this.thread.x]); + return this.thread.x > 1 ? poly(a[0]) : safe; + }, { functions: [poly] }); +}); + +test('cpu bail: an early return this pass cannot fold', () => { + assertUntouched('cpu', 'return inside a loop', function (a) { + return search(a, this.thread.x); + }, { + functions: [function search(m, k) { + for (let i = 0; i < 4; i++) { + if (m[i] > k) return i; + } + return -1; + }], + }, [[1, 2, 3, 4]]); +}); + +test('cpu bail: a helper that declares a function keeps its call', () => { + // cloning a nested declaration would register the same helper twice -- the + // builder keys them by AST identity -- so `wrapper` stays a function. The + // function it declares is its own plan entry and still inlines INTO it. + const source = cpuSource(function (a) { + return wrapper(a[this.thread.x]); + }, { + functions: [function wrapper(v) { + function twice(w) { + return w * 2; + } + return twice(v) + 1; + }], + }); + assert.ok(/function wrapper\(/.test(source), 'the declaring helper survives'); + assert.ok(/wrapper\(user_a\[(?:x|_this\.thread\.x)\]\)/.test(source.replace(/\s/g, '')), 'and is still called'); + assert.notOk(/twice\(/.test(source), 'the function it declares inlined into it'); +}); + +test('cpu bail: a native function of the same name wins', () => { + // natives deliberately override a JavaScript function of the same name at + // emission, so the body registered under that name is not what runs + const gl = GL_MODE; + if (!gl) { + assert.ok(true, 'no GL backend here'); + return; + } + assertUntouched(gl, 'native override', function (a) { + return divide(a[this.thread.x], 2); + }, { + functions: [function divide(p, q) { + return p / q; + }], + nativeFunctions: [{ + name: 'divide', + source: 'float divide(float a, float b) {\n return a + b;\n}', + }], + }); +}); + +test('cpu bail: a sub-kernel is never a callee', () => { + const gpu = new GPU({ mode: 'cpu' }); + try { + const kernel = gpu.createKernelMap({ + doubled: function doubled(v) { + return v * 2; + }, + }, function (a) { + const v = poly(a[this.thread.x]); + doubled(v); + return v; + }, { output: [4], functions: [poly], _inliningDisabled: false }); + kernel([1, 2, 3, 4]); + const source = kernel.kernel.kernelString; + assert.notOk(/function poly\(/.test(source), 'the helper inlined'); + assert.ok(/function doubled\(/.test(source), 'the sub-kernel did not'); + } finally { + gpu.destroy(); + } +}); + +(GL_MODE ? test : skip)('gl: the division helper is skipped only where it provably does nothing', () => { + // `divWithIntCheck` recovers an exact quotient when BOTH operands are whole + // numbers, and returns `x / y` otherwise. A fractional literal settles that + // statically -- and only statically: the value is the same either way on + // hardware whose integer divide is already accurate, which is every device + // this suite can reach, so emission is the only place the difference shows. + const source = build(GL_MODE, function (a) { + return a[this.thread.x] / 2 + a[this.thread.x] / 2.5; + }, { fixIntegerDivisionAccuracy: true }).source; + assert.ok(/divWithIntCheck\(/.test(source), 'a whole-number divisor keeps the check'); + assert.equal((source.match(/divWithIntCheck\(/g) || []).length, 1, + 'the fractional divisor does not'); + const off = build(GL_MODE, function (a) { + return a[this.thread.x] / 2 + a[this.thread.x] / 2.5; + }, { fixIntegerDivisionAccuracy: false }).source; + assert.notOk(/divWithIntCheck\(/.test(off), 'and nothing is wrapped with the fix off'); +}); + +test('the internal switch turns only inlining off', () => { + const source = cpuSource(function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += poly(a[this.thread.x]); + return s; + }, { functions: [poly], _inliningDisabled: true }); + assert.ok(/function poly\(/.test(source), 'the helper survives'); + assert.ok(/const user_optHoist0=/.test(source), 'and hoisting still ran'); +}); + +// ------------------------------------------------------------- the plan + +// The call graph's verdicts, asked directly. Recursion is the reason: gpu.js +// cannot emit a recursive helper at all, so there is no kernel whose emission +// could show that T2 declined to inline one -- the only way to assert the +// skip is to ask the plan. + +function planFor(sources) { + const functionMap = {}; + for (const source of sources) { + const node = { + name: source.slice(9, source.indexOf('(')).trim(), + isRootKernel: false, + isSubKernel: false, + source, + _rawAST: null, + getRawAST: FunctionNode.prototype.getRawAST, + requiresSequenceFreeForInit: false, + }; + functionMap[node.name] = node; + } + functionMap.kernel.isRootKernel = true; + const builder = Object.assign(Object.create(FunctionBuilder.prototype), { + functionMap, + nativeFunctionNames: [], + kernel: { constants: null }, + _inlinePlan: null, + }); + return { + has: name => Boolean(builder.lookupInlineTarget(name)), + }; +} + +test('plan: a self-recursive helper is never inlined', () => { + const plan = planFor([ + 'function kernel(a) { return fact(3) + a[0]; }', + 'function fact(n) { if (n <= 1) return 1; return n * fact(n - 1); }', + ]); + assert.notOk(plan.has('fact'), 'fact is left as a call'); +}); + +test('plan: a mutually recursive pair is never inlined', () => { + const plan = planFor([ + 'function kernel(a) { return ping(a[0]); }', + 'function ping(v) { return pong(v) + 1; }', + 'function pong(v) { return ping(v) * 2; }', + ]); + assert.notOk(plan.has('ping'), 'ping is left as a call'); + assert.notOk(plan.has('pong'), 'pong is left as a call'); +}); + +test('plan: an ordinary chain is inlinable at every level', () => { + const plan = planFor([ + 'function kernel(a) { return one(a[0]); }', + 'function one(v) { return two(v) + 1; }', + 'function two(v) { return v * 2; }', + ]); + assert.ok(plan.has('one') && plan.has('two'), 'both levels inline'); + assert.notOk(plan.has('kernel'), 'the root is never a callee'); +}); + +test('plan: a helper referencing an identifier it does not declare is not inlined', () => { + // inlining it would bind `stray` to whatever the caller happens to have + // named that -- capture, not inlining + const plan = planFor([ + 'function kernel(a) { return leaky(a[0]); }', + 'function leaky(v) { return v + stray; }', + ]); + assert.notOk(plan.has('leaky'), 'the free identifier stops it'); +}); + +test('plan: the size budget sheds the largest helper first', () => { + const big = `function big(v) { return ${ new Array(400).fill('v').join(' + ') }; }`; + // separate statements: a call this pass will not inline is opaque, so a + // second call in the SAME statement cannot be hoisted past it either + const plan = planFor([ + 'function kernel(a) { const p = big(a[0]); const q = small(a[1]); return p + q; }', + big, + 'function small(v) { return v * 2; }', + ]); + assert.notOk(plan.has('big'), 'the oversized helper keeps its call'); + assert.ok(plan.has('small'), 'the small one still inlines'); +}); diff --git a/test/features/optimizer/parity.js b/test/features/optimizer/parity.js new file mode 100644 index 00000000..a785d4de --- /dev/null +++ b/test/features/optimizer/parity.js @@ -0,0 +1,1219 @@ +const { assert, skip, test, module: describe } = require('qunit'); +const { GPU, input } = require('../../../src'); + +describe('features: optimizer parity'); + +// THE gate for the compiler optimizations: every kernel below is built twice +// on the SAME backend -- once normally, once with `_optimizerDisabled` -- and +// the two results must agree BIT FOR BIT. Not approximately, and not across +// backends: cpu computes in f64 and everything else in f32, so cross-backend +// agreement is a different (and looser) question that other suites already +// ask. What this file proves is that turning the optimizer on changes nothing +// a caller can observe. +// +// The table is the point. A transform lands with rows here, not with rows in +// its own file: a shape that only the unroller touches still has to survive +// hoisting and inlining, and the cheapest way to keep that true is for every +// phase to add cases to one battery every phase runs. +// +// Rows cover the spec's shapes (hot-loop reads, helpers, tiny literal loops, +// stencils, and a control with none of it) crossed with the settings that +// change emission -- strictIntegers, fixIntegerDivisionAccuracy, seeded +// random, sub-kernels, Input arguments, dynamic output and dynamic arguments +// -- plus the #865/#867 control-flow shapes, which are exactly the places a +// naive hoist or unroll would change when something runs. + +const MODES = [ + ['cpu', () => true], + ['webgl', () => GPU.isWebGLSupported], + ['webgl2', () => GPU.isWebGL2Supported], + ['headlessgl', () => GPU.isHeadlessGLSupported], + ['webasm', () => GPU.isWebAssemblySupported], +]; + +// navigator.gpu can be present with no adapter (headless Chromium, blocklisted +// GPUs); QUnit cannot skip at runtime, so an adapterless environment records a +// pass with an explicit message and bumps a counter the headed canary rejects. +let adapterPromise = null; +async function webgpuAdapter(assert) { + if (!adapterPromise) adapterPromise = navigator.gpu.requestAdapter(); + const adapter = await adapterPromise; + if (!adapter) { + if (typeof window !== 'undefined') { + window.__webgpuRuntimeSkips = (window.__webgpuRuntimeSkips || 0) + 1; + } + assert.ok(true, 'navigator.gpu present but no adapter (headless/blocklisted) — runtime skip'); + } + return adapter; +} + +/** + * Every number a kernel call produced, in order, whatever container it came + * back in -- a typed array, nested rows, or a kernel map's named results. + */ +function flattenValues(result, out) { + if (result === null || result === undefined) return out; + if (typeof result === 'number') { + out.push(result); + return out; + } + if (typeof result.length === 'number') { + for (let i = 0; i < result.length; i++) flattenValues(result[i], out); + return out; + } + const names = Object.keys(result).sort(); + for (let i = 0; i < names.length; i++) flattenValues(result[names[i]], out); + return out; +} + +/** + * The comparison is on the bits, never on the values: `===` on numbers calls + * NaN unequal to itself and -0 equal to 0, and both of those are differences + * a caller can see. Doubles rather than floats so a cpu result is compared at + * the precision it was computed at, not at the precision that would hide a + * disagreement. + */ +function bitsOf(values) { + const doubles = new Float64Array(values.length); + doubles.set(values); + return new Int32Array(doubles.buffer); +} + +/** + * Backends whose emitted program is handed to a compiler WE do not own, and + * which is licensed to reassociate float arithmetic (GLSL ES 4.1.4 lets an + * implementation carry an operation out at higher precision, and every shader + * compiler in the fleet algebraically simplifies). Semantically identical + * source is not enough to pin the bits there: hoisting `a[x]` out of + * `s += a[x] * (i + 1)` lets the driver factor the unrolled sum into `x * 10` + * where four separate fetches kept it as four adds -- measured at one f32 ULP + * on headless-gl. That is the driver reassociating, not the pass: the pass + * itself never reassociates and never CSEs across a float operation. + * + * cpu and webasm have no such licence. Emitted JavaScript runs under IEEE-754 + * with no reassociation, and wasm f32/f64 opcodes are exactly specified, so + * those two are held to the bit. + */ +const driverMayReassociate = ['webgl', 'webgl2', 'headlessgl', 'webgpu']; + +// one f32 ULP is 6e-8 relative; this is a few of them, and about ten times +// tighter than the tolerance the cross-backend suites use +const REASSOCIATION_TOLERANCE = 1e-6; + +function assertParity(assert, optimized, disabled, mode, label) { + const left = flattenValues(optimized, []); + const right = flattenValues(disabled, []); + assert.equal(left.length, right.length, `${ label }: result length`); + if (left.length !== right.length) return; + + const leftBits = bitsOf(left); + const rightBits = bitsOf(right); + let firstDifferent = -1; + for (let i = 0; i < leftBits.length; i++) { + if (leftBits[i] !== rightBits[i]) { + firstDifferent = i >> 1; + break; + } + } + if (firstDifferent === -1) { + assert.ok(true, `${ label }: ${ left.length } values bit-identical`); + return; + } + if (driverMayReassociate.indexOf(mode) === -1) { + assert.ok(false, + `${ label }: cell ${ firstDifferent } differs — optimized ${ left[firstDifferent] }, ` + + `disabled ${ right[firstDifferent] }`); + return; + } + let worst = 0; + let worstCell = 0; + for (let i = 0; i < left.length; i++) { + // floored at 1: a sum whose terms cancel to near zero has no meaningful + // relative scale, and the question here is the size of the drift + const scale = Math.max(Math.abs(left[i]), Math.abs(right[i]), 1); + const error = Math.abs(left[i] - right[i]) / scale; + if (error > worst) { + worst = error; + worstCell = i; + } + } + assert.ok(worst <= REASSOCIATION_TOLERANCE, + `${ label }: shader compiler reassociated (worst relative ${ worst.toExponential(2) } at cell ` + + `${ worstCell }: optimized ${ left[worstCell] }, disabled ${ right[worstCell] })`); +} + +// ------------------------------------------------------------------- shapes + +function poly(x) { + return x * x * 0.5 + x * 0.25 - 0.125; +} + +function scale(x, by) { + return poly(x) * by; +} + +function outer(x) { + return scale(x, 2) + 1; +} + +const VECTOR = []; +for (let i = 0; i < 16; i++) VECTOR.push(((i * 13) % 100) / 50 - 1); + +const MATRIX = []; +for (let y = 0; y < 8; y++) { + const row = []; + for (let x = 0; x < 8; x++) row.push(((x * 31 + y * 17) % 100) / 100); + MATRIX.push(row); +} + +const CASES = [ + { + name: 'H: invariant read in a hot loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'H: invariant constant read in a hot loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 6; i++) { + s += a[this.thread.x] * this.constants.m[2][3] + i; + } + return s; + }, + output: [16], + settings: { constants: { m: MATRIX } }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'H: mixed invariant and varying subscripts', + kernel: function (a, b) { + let s = 0; + for (let i = 0; i < 8; i++) { + s += a[this.thread.y][i] * b[3][this.thread.x]; + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX, MATRIX] }], + }, + { + name: 'H: read invariant to a whole loop nest', + kernel: function (a) { + let s = 0; + for (let y = 0; y < 3; y++) { + for (let x = 0; x < 3; x++) { + s += a[1][2] + y * 0.5 + x * 0.25; + } + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX] }], + }, + { + name: 'H bail: read under a conditional', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 8; i++) { + if (i > this.thread.x) { + s += a[1][2]; + } + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX] }], + }, + { + // the read is invariant and unconditional, but a cell whose loop runs zero + // times never performs it -- and on cpu a two-level read past the end + // THROWS rather than reading a clamped texel. Hoisting it out of a loop + // with no provable first iteration would turn a working kernel into a + // crash, which is the one difference bigger than a bit. + name: 'H bail: out-of-range read in a loop that may not run', + kernel: function (a) { + let s = 0; + for (let i = 0; i < this.thread.x; i++) { + s += a[this.thread.x + 100][2]; + } + return s; + }, + output: [1], + settings: { loopMaxIterations: 10 }, + calls: [{ args: [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] }], + modes: ['cpu'], + }, + { + // an out-of-range read the guard keeps the un-optimized build from ever + // performing; hoisting past the guard reads it for every cell + name: 'H bail: out-of-range read under a guard', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) { + if (this.thread.x < 0) { + s += a[this.thread.x + 100][2]; + } + } + return s; + }, + output: [3], + calls: [{ args: [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] }], + modes: ['cpu'], + }, + { + name: 'H bail: subscript assigned in the body', + kernel: function (a) { + let k = 0; + let s = 0; + for (let i = 0; i < 8; i++) { + s += a[1][k]; + k = (k + 1) % 8; + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX] }], + }, + { + name: 'H bail: reassigned array argument (#865)', + kernel: function (b, a) { + a = b; + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x]; + return s; + }, + output: [8], + calls: [{ args: [VECTOR, VECTOR.slice().reverse()] }], + // reassigning an ARRAY argument is a cpu-only shape: the GL backends bind + // arrays as samplers and webasm as memory views, neither assignable (#865) + modes: ['cpu'], + }, + { + name: 'H bail: early return inside the loop (#865)', + kernel: function (a) { + for (let i = 0; i < 20; i++) { + if (i * i > this.thread.x) { + return i * 100 + a[1][2]; + } + } + return -1; + }, + output: [8, 8], + settings: { loopMaxIterations: 30 }, + calls: [{ args: [MATRIX] }], + }, + { + name: 'do-while with continue (#865)', + kernel: function (a) { + let i = 0; + let acc = 0; + do { + i++; + if (i % 3 === 0) continue; + acc += i + a[1][2]; + } while (i < 12); + return acc; + }, + output: [8], + settings: { loopMaxIterations: 30 }, + calls: [{ args: [MATRIX] }], + }, + { + name: 'while loop with an invariant read', + kernel: function (a) { + let i = 0; + let s = 0; + while (i < 6) { + s += a[this.thread.x] * 2; + i++; + } + return s; + }, + output: [16], + settings: { loopMaxIterations: 30 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'assigning to a scalar argument (#867)', + kernel: function (base, a) { + base = base + this.thread.x; + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * base; + return s; + }, + output: [16], + calls: [{ args: [10, VECTOR] }], + // the webgpu backend binds scalar arguments as uniform params and has no + // per-cell shadow for them yet, so this shape does not build there at all + // -- with the optimizer on or off + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webasm'], + }, + { + name: 'switch/case in the loop body (#855)', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) { + switch (i) { + case 0: + s += a[this.thread.x]; + break; + case 1: + s += a[this.thread.x] * 2; + break; + default: + s -= 1; + } + } + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 shape: helper in a hot loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 8; i++) s += poly(a[this.thread.x] + i * 0.01); + return s; + }, + output: [16], + settings: { functions: [poly] }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 shape: helper calling helper', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += scale(a[this.thread.x], i + 1); + return s; + }, + output: [16], + settings: { functions: [poly, scale] }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3 shape: literal 3-trip loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 3; i++) s += a[this.thread.x] * (i + 1) + i; + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3 shape: literal loop above the unroll limit', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 32; i++) s += a[this.thread.x] * 0.5 + i; + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: exactly at the unroll limit', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 8; i++) s += a[i] * (i + 1); + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: one trip past the unroll limit', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 9; i++) s += a[i] * (i + 1); + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: a raised unroll limit', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 9; i++) s += a[i] * (i + 1); + return s; + }, + output: [16], + settings: { loopUnrollLimit: 16 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: unrolling turned off', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[i] * (i + 1); + return s; + }, + output: [16], + settings: { loopUnrollLimit: 0 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: nested literal loops', + kernel: function (a) { + let s = 0; + for (let y = 0; y < 3; y++) { + for (let x = 0; x < 3; x++) { + s += a[y][x] * (y + 1) - x * 0.25; + } + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX] }], + }, + { + name: 'T3: a literal loop inside a helper', + kernel: function (a) { + return rowSum(a, this.thread.y) + a[this.thread.y][this.thread.x]; + }, + output: [8, 8], + settings: { + functions: [function rowSum(m, y) { + let s = 0; + for (let i = 0; i < 4; i++) s += m[y][i] * (i + 1); + return s; + }], + }, + calls: [{ args: [MATRIX] }], + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T3: a counter counting down', + kernel: function (a) { + let s = 0; + for (let i = 3; i > 0; i--) s += a[i] * i; + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + // a decrementing counter does not compile on webgpu with the optimizer + // OFF: the loop variable decays to `f32` and WGSL allows `--` only on an + // integer scalar. Unrolling deletes the loop and the kernel then runs, + // which is a difference in whether the shape builds at all -- a + // pre-existing webgpu defect the optimizer happens to route around + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webasm'], + }, + { + // the subscript is arithmetic on the counter, so unrolling leaves an index + // made only of numbers -- an integer context whose operands no longer say + // so on their own + name: 'T3: a negative counter, offset into the subscript', + kernel: function (a) { + let s = 0; + for (let i = -2; i < 2; i++) s += a[i + 2] * i + a[2 - i] * 0.5; + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: a counter stepping by two', + kernel: function (a) { + let s = 0; + for (let j = 0; j < 8; j += 2) s += a[j] * 0.5; + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: a switch on the counter', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 3; i++) { + switch (i) { + case 0: + s += a[this.thread.x]; + break; + case 1: + s += a[this.thread.x] * 2; + break; + default: + s -= 0.5; + } + } + return s; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3: an early return out of an unrolled iteration (#865)', + kernel: function (a) { + for (let i = 0; i < 4; i++) { + if (a[i] > 0) return i * 10 + a[i]; + } + return -1; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3 bail: a break in the body', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) { + if (a[i] > 0.5) break; + s += a[i]; + } + return s; + }, + output: [16], + settings: { loopMaxIterations: 20 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3 bail: a body that writes the counter', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 6; i++) { + s += a[i]; + if (a[i] < 0) i++; + } + return s; + }, + output: [16], + settings: { loopMaxIterations: 20 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T3 bail: an inner loop shadowing the counter', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 3; i++) { + for (let i = 0; i < n; i++) { + s += a[i] * 0.5; + } + } + return s; + }, + output: [16], + settings: { loopMaxIterations: 20, argumentTypes: ['Array', 'Integer'] }, + calls: [{ args: [VECTOR, 4] }], + }, + { + // `this.thread.x` names `x` as a FIELD, not as a variable; a substitution + // that walks into a non-computed member's property rewrites it + name: 'T3: a counter named for a coordinate', + kernel: function (a) { + let s = 0; + for (let x = 0; x < 3; x++) { + s += a[x] * this.thread.x + this.thread.y; + } + return s; + }, + output: [8, 8], + calls: [{ args: [MATRIX[0]] }], + }, + { + name: 'T3 bail: a fractional counter', + kernel: function (a) { + let s = 0; + for (let t = 0; t < 1; t += 0.25) s += a[this.thread.x] * t; + return s; + }, + output: [16], + settings: { loopMaxIterations: 20 }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T1: every coordinate read, on every rank', + kernel: function (a) { + return a[this.thread.z][this.thread.y][this.thread.x] * 2 + + this.thread.x - this.thread.y * 0.5 + this.thread.z * 0.25; + }, + output: [4, 4, 2], + calls: [{ args: [[MATRIX.slice(0, 4), MATRIX.slice(4, 8)]] }], + }, + { + name: 'T1: a coordinate read inside a helper and in the body', + kernel: function (a) { + return column(a) + this.thread.x * 0.5; + }, + output: [8, 8], + settings: { + functions: [function column(m) { + return m[this.thread.y][this.thread.x]; + }], + }, + calls: [{ args: [MATRIX] }], + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T1: coordinates, constants and output together', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 3; i++) { + s += a[this.thread.y][this.thread.x] * this.constants.k[i] + this.output.x - this.thread.y; + } + return s; + }, + output: [8, 8], + settings: { constants: { k: [0.25, 0.5, 0.75] } }, + calls: [{ args: [MATRIX] }], + }, + { + name: 'stencil 3x3', + kernel: function (a) { + let s = 0; + for (let dy = -1; dy <= 1; dy++) { + for (let dx = -1; dx <= 1; dx++) { + const y = Math.min(Math.max(this.thread.y + dy, 0), 7); + const x = Math.min(Math.max(this.thread.x + dx, 0), 7); + s += a[y][x]; + } + } + return s / 9; + }, + output: [8, 8], + calls: [{ args: [MATRIX] }], + }, + { + name: 'control: no loops, no helpers', + kernel: function (a) { + const x = a[this.thread.x]; + return x * x * 0.5 + Math.sqrt(Math.abs(x)) - x * 0.25; + }, + output: [16], + calls: [{ args: [VECTOR] }], + }, + { + name: 'strictIntegers', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * n + i; + return s; + }, + output: [16], + settings: { strictIntegers: true, argumentTypes: ['Array', 'Integer'] }, + calls: [{ args: [VECTOR, 3] }], + }, + { + name: 'fixIntegerDivisionAccuracy', + kernel: function (a) { + let s = 0; + for (let i = 1; i < 5; i++) s += a[this.thread.x] / i + this.thread.x / i; + return s; + }, + output: [16], + settings: { fixIntegerDivisionAccuracy: true }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'Input argument', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[1][2] + a[this.thread.y][this.thread.x] * i; + return s; + }, + output: [8, 8], + settings: { argumentTypes: ['Input'] }, + calls: [{ args: [() => input(new Float32Array(64).map((v, i) => (i % 17) / 17), [8, 8])] }], + }, + { + name: 'dynamic output', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[0] * i + this.output.x; + return s; + }, + output: [8], + settings: { dynamicOutput: true }, + calls: [ + { args: [VECTOR] }, + { output: [12], args: [VECTOR] }, + ], + }, + { + name: 'dynamic arguments', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[1] * i + a[this.thread.x % 4]; + return s; + }, + output: [8], + settings: { dynamicArguments: true }, + calls: [ + { args: [VECTOR.slice(0, 8)] }, + { args: [VECTOR.slice(0, 12)] }, + ], + }, + { + name: 'sub-kernels', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + subKernelDouble(a[this.thread.x]); + return s; + }, + subKernels: { doubled: function subKernelDouble(v) { return v * 2; } }, + output: [16], + calls: [{ args: [VECTOR] }], + // the webgpu backend does not implement createKernelMap; webasm degrades + // to cpu for it, which is still an optimized-vs-disabled comparison + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webasm'], + }, + { + name: 'Array(3) return type', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += a[this.thread.x] * (i + 1); + return [s, s * 2, s * 0.5]; + }, + output: [16], + settings: { precision: 'single' }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'seeded random in a hot loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += Math.random() * a[this.thread.x]; + return s; + }, + output: [16], + settings: { randomSeed: 42 }, + calls: [{ args: [VECTOR] }], + // cpu's Math.random is unseeded by design, so two cpu builds cannot agree + // on a random stream and the row would be testing the RNG, not the pass + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + { + // the same shape below the unroll limit, which is where the unroller would + // reach it. The draw sequence is preserved either way -- same count, same + // order -- but the GL lowering of Math.random is + // `fract(sin(dot(...)) * 43758.5453)`, which turns one ULP of compiler + // reassociation into a different number entirely. Measured 4.5e-4 apart on + // ANGLE/Metal before the unroller learned to leave these loops alone. + name: 'seeded random in a tiny literal loop', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 3; i++) s += Math.random() * a[this.thread.x] + i; + return s; + }, + output: [16], + settings: { randomSeed: 11 }, + calls: [{ args: [VECTOR] }], + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + { + name: 'seeded random inside a helper', + kernel: function (a) { + let s = 0; + for (let i = 0; i < 4; i++) s += jitter(a[this.thread.x]); + return s; + }, + settings: { + randomSeed: 7, + functions: [function jitter(v) { return v + Math.random() * 0.5; }], + }, + output: [16], + calls: [{ args: [VECTOR] }], + // GL compiles this now: the random plugin is selected by matching the + // kernel's source, and a helper added with addFunction is part of the same + // shader but was never part of that match + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + + // ------------------------------------------------------------- T2 battery + // + // The edge list the design contract names for inlining, one row each. A row + // that must SKIP is here for the same reason as one that must transform: an + // over-eager bail and an over-eager inline are both failures, and only the + // pair of files can tell them apart -- this one says the answer did not + // move, inlining.js says the emission did (or did not). + { + name: 'T2: helper calling helper, three deep', + kernel: function (a) { + return outer(a[this.thread.x]) + outer(a[0]); + }, + output: [16], + settings: { functions: [poly, scale, outer] }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2: a parameter reassigned inside the helper', + kernel: function (a) { + return bump(a[this.thread.x]) + bump(a[this.thread.x] * 2); + }, + output: [16], + settings: { + functions: [function bump(v) { + v = v + 1; + v *= 0.5; + return v * v; + }], + }, + calls: [{ args: [VECTOR] }], + // WGSL parameters are immutable, so the un-optimized build cannot compile + // the assignment at all (#867's shape, one level in); inlining binds the + // parameter as an ordinary mutable local + enabledByInlining: ['webgpu'], + }, + { + name: 'T2: an array argument, aliased into both parameters', + kernel: function (a) { + return blend(a, a, this.thread.x); + }, + output: [16], + settings: { + functions: [function blend(m, n, k) { + return m[k] * 0.25 + n[(k + 1) % 16] * 0.75; + }], + }, + calls: [{ args: [VECTOR] }], + // an array parameter is a hard error on webasm AND webgpu; inlining + // removes the parameter, so this is a shape T2 makes buildable + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T2: helper locals shadowing kernel locals', + kernel: function (a) { + const v = a[this.thread.x]; + const t = v * 2; + const s = shadowy(v) + shadowy(t); + return s + v + t; + }, + output: [16], + settings: { + functions: [function shadowy(v) { + const t = v * 3; + const s = t + v; + return s * t; + }], + }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2: an early return inside a helper', + kernel: function (a) { + return clampish(a[this.thread.x]) + clampish(a[this.thread.x] - 0.5); + }, + output: [16], + settings: { + functions: [function clampish(v) { + if (v < 0) return 0; + if (v > 0.5) return 1; + return v * 2; + }], + }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 skip: a return this pass cannot fold to an expression', + kernel: function (a) { + return firstOver(a, this.thread.x * 0.05); + }, + output: [16], + settings: { + functions: [function firstOver(m, limit) { + for (let i = 0; i < 8; i++) { + if (m[i] > limit) return i; + } + return -1; + }], + }, + calls: [{ args: [VECTOR] }], + // the helper survives, so its array parameter still cannot be emitted on + // webasm -- identically on both sides, which is what the row asserts + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webgpu'], + }, + { + name: 'T2 skip: an early return whose branches draw', + // folding this to a conditional would be wrong on webasm's vector path, + // which evaluates BOTH sides of a conditional for every lane before + // selecting -- so a draw in the untaken branch would advance a stream the + // function never touched + kernel: function (a) { + return maybeDraw(a[this.thread.x]) + Math.random(); + }, + output: [16], + settings: { + randomSeed: 5, + functions: [function maybeDraw(v) { + if (v < 0) return Math.random(); + return v * 2; + }], + }, + calls: [{ args: [VECTOR] }], + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + { + name: 'T2 skip: a call in a conditional operand', + kernel: function (a) { + return this.thread.x > 4 ? poly(a[this.thread.x]) : poly(a[0]); + }, + output: [16], + settings: { functions: [poly] }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 skip: a call after an update in the same statement', + kernel: function (a) { + let k = 0; + let s = 0; + s += a[k++] * poly(a[this.thread.x]); + return s + k; + }, + output: [16], + settings: { functions: [poly] }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2: seeded random inside a helper, scalar and vector dispatch', + // 6 wide: webasm runs a vector span plus a scalar tail per row, so both + // dispatch paths draw from the same seeded stream in one run. That is the + // sharpest edge in the feature -- un-inlined, a helper's draws come from + // the scalar PCG with per-lane state swapped around the call; inlined, + // they come from the vector PCG directly + kernel: function (a) { + const p = Math.random(); + const q = jitter(a[this.thread.x % 8]); + return p + q + Math.random(); + }, + output: [6, 4], + settings: { + randomSeed: 1234, + functions: [function jitter(v) { return v + Math.random() * 0.5; }], + }, + calls: [{ args: [VECTOR] }], + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + { + name: 'T2: seeded random in a helper under a branch', + kernel: function (a) { + let s = a[this.thread.x % 8]; + if (this.thread.x % 2 === 0) { + s += jitter(s); + } + return s + Math.random(); + }, + output: [7, 3], + settings: { + randomSeed: 99, + functions: [function jitter(v) { return v + Math.random() * 0.5; }], + }, + calls: [{ args: [VECTOR] }], + modes: ['webgl', 'webgl2', 'headlessgl', 'webasm', 'webgpu'], + }, + { + name: 'T2: a sub-kernel calling a helper', + kernel: function (a) { + const v = poly(a[this.thread.x]); + subPoly(a[this.thread.x] * 2); + return v; + }, + subKernels: { subPoly: function subPoly(v) { return poly(v) + 1; } }, + output: [16], + settings: { functions: [poly] }, + calls: [{ args: [VECTOR] }], + // kernel maps fall back to cpu on webasm, which would compare a cpu build + // against a cpu build under a webasm label + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webgpu'], + }, + { + name: 'T2: a helper reading thread and constants', + kernel: function (a) { + return corner(a) + this.thread.x * 0.5; + }, + output: [8, 8], + settings: { + constants: { k: 0.375 }, + functions: [function corner(m) { + return m[this.thread.y][this.thread.x] * this.constants.k; + }], + }, + calls: [{ args: [MATRIX] }], + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T2: an Integer-typed argument through a helper', + // the binding a non-atom argument gets is typed from the argument, and an + // integer expression that is not a member read declares as a float. Whole + // numbers survive that round trip exactly at these magnitudes; the row is + // here so a change to that reasoning shows up as a failure + kernel: function (a) { + return pick(a, Math.floor(this.thread.x / 2) + 1) + pick(a, this.thread.x); + }, + output: [16], + settings: { + functions: [function pick(m, k) { + return m[k % 16] * (k + 1); + }], + }, + calls: [{ args: [VECTOR] }], + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T2: a void helper in statement position', + kernel: function (a) { + const v = a[this.thread.x]; + note(v); + return v * 2; + }, + output: [16], + settings: { + functions: [function note(v) { + const unused = v * v + 1; + }], + }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 then T3: a helper carrying a tiny loop into a caller', + kernel: function (a) { + return rowish(a, this.thread.x) + a[this.thread.x]; + }, + output: [16], + settings: { + functions: [function rowish(m, k) { + let s = 0; + for (let i = 0; i < 3; i++) s += m[(k + i) % 16] * (i + 1); + return s; + }], + }, + calls: [{ args: [VECTOR] }], + enabledByInlining: ['webasm', 'webgpu'], + }, + { + name: 'T2 under strictIntegers and fixIntegerDivisionAccuracy', + kernel: function (a) { + return ratio(a[this.thread.x], this.thread.x + 1) + ratio(a[0], 4); + }, + output: [16], + settings: { + strictIntegers: true, + fixIntegerDivisionAccuracy: true, + functions: [function ratio(v, d) { + return v / d + (d % 3) * 0.5 + v / 2.5; + }], + }, + calls: [{ args: [VECTOR] }], + }, + { + name: 'T2 with a dynamic output and a helper', + kernel: function (a) { + return poly(a[this.thread.x % 8]) * this.output.x; + }, + output: [8], + settings: { functions: [poly], dynamicOutput: true }, + calls: [{ args: [VECTOR] }, { output: [16], args: [VECTOR] }], + }, + { + name: 'minified source, comma-folded', + // exactly what a bundler emits: statement sequences folded into commas and + // an if folded into a short circuit. De-minification runs before the + // optimizer, so the pass must see plain statements here. + kernel: 'function(a){let s=0,i=0;for(i=0;i<4;i++)s+=a[this.thread.x]*(i+1),i%2===0&&(s+=1);return s}', + output: [16], + calls: [{ args: [VECTOR] }], + // webgpu is the backend that hoists a comma for-init out of the header, + // and its astForStatement then reads the init it just nulled -- a + // pre-existing crash on this shape, optimizer or no optimizer + modes: ['cpu', 'webgl', 'webgl2', 'headlessgl', 'webasm'], + }, +]; + +// ------------------------------------------------------------------- runner + +function makeKernel(gpu, spec, disabled) { + const settings = Object.assign( + { output: spec.output }, + spec.settings || {}, + { _optimizerDisabled: disabled }); + if (spec.subKernels) { + return gpu.createKernelMap(spec.subKernels, spec.kernel, settings); + } + return gpu.createKernel(spec.kernel, settings); +} + +function resolveArgs(args) { + return args.map(argument => (typeof argument === 'function' ? argument() : argument)); +} + +/** + * Builds one side and runs every call, keeping a build failure rather than + * throwing it: a shape a device cannot compile at all (no draw buffers, no + * float textures) fails identically with the optimizer on and off, and that + * says nothing about the optimizer. A failure on ONE side only is the whole + * point of this file and stays a failure. + */ +async function collect(gpu, spec, disabled) { + const results = []; + try { + const kernel = makeKernel(gpu, spec, disabled); + for (let i = 0; i < spec.calls.length; i++) { + const call = spec.calls[i]; + if (call.output) kernel.setOutput(call.output); + results.push(await kernel.apply(null, resolveArgs(call.args))); + } + return { results, error: null, kernel: kernel.kernel }; + } catch (e) { + return { results, error: e.message || String(e), kernel: null }; + } +} + +async function runCase(assert, mode, spec) { + const gpu = new GPU({ mode }); + try { + const optimized = await collect(gpu, spec, false); + const disabled = await collect(gpu, spec, true); + + // T2 makes a few shapes compile that never compiled before -- a helper + // taking an array argument is a hard error on webasm, and inlining leaves + // no helper to take one. A row says so explicitly; the assertion still + // fails if the disabled build starts working or the optimized one stops. + const enabled = spec.enabledByInlining && spec.enabledByInlining.indexOf(mode) > -1; + if (enabled && optimized.error === null && disabled.error !== null) { + assert.ok(true, `${ spec.name } / ${ mode }: inlining makes this shape buildable ` + + `(un-optimized: ${ disabled.error.split('\n')[0] })`); + return; + } + if (optimized.error !== null || disabled.error !== null) { + assert.equal(optimized.error, disabled.error, + `${ spec.name } / ${ mode }: the optimizer decides nothing about whether this shape builds`); + return; + } + + // a build-time throw from the optimizer degrades to an un-optimized + // build (#868), which would make every row below compare two identical + // un-optimized kernels and pass for the wrong reason + assert.notOk(optimized.kernel._optimizerDisabled, + `${ spec.name } / ${ mode }: the optimized build stayed optimized ` + + `(${ optimized.kernel.fallbackReason || 'no fallback' })`); + + for (let i = 0; i < optimized.results.length; i++) { + assertParity(assert, optimized.results[i], disabled.results[i], mode, + `${ spec.name } / ${ mode } / call ${ i }`); + } + } finally { + await gpu.destroy(); + } +} + +for (let c = 0; c < CASES.length; c++) { + const spec = CASES[c]; + for (let m = 0; m < MODES.length; m++) { + const [mode, supported] = MODES[m]; + const applies = !spec.modes || spec.modes.indexOf(mode) > -1; + const runner = applies && supported() ? test : skip; + runner(`${ spec.name } ${ mode }`, assert => runCase(assert, mode, spec)); + } + const webgpuApplies = !spec.modes || spec.modes.indexOf('webgpu') > -1; + (webgpuApplies && GPU.isWebGPUSupported ? test : skip)(`${ spec.name } webgpu`, async assert => { + if (!(await webgpuAdapter(assert))) return; + return runCase(assert, 'webgpu', spec); + }); +} diff --git a/test/features/optimizer/unrolling.js b/test/features/optimizer/unrolling.js new file mode 100644 index 00000000..15e071f2 --- /dev/null +++ b/test/features/optimizer/unrolling.js @@ -0,0 +1,462 @@ +const { assert, skip, test, module: describe } = require('qunit'); +const { GPU } = require('../../../src'); + +describe('features: optimizer unrolling and thread localization'); + +// Parity proves T3 and T1 change no answer. These prove they change the +// EMISSION -- in both directions, because a transform that quietly does +// nothing also passes every parity row. Each shape is asserted against the +// text the backend actually compiles: the cpu backend's generated JavaScript +// and the GL backends' generated GLSL. + +// T1 ships OFF (a measured net loss at scale, see optimizer.threadLocalName), +// but the transform stays verified for whoever revisits it: these rows turn +// it on explicitly. +const T1_ON = { localizeThreadCoordinates: true }; +function T1_TEST(name, body) { + test(name, assert => { + const originalSource = cpuSource; + const originalBuild = cpuBuild; + cpuSource = (kernelSource, settings, args) => + originalSource(kernelSource, Object.assign({}, T1_ON, settings), args); + cpuBuild = (kernelSource, settings, args) => + originalBuild(kernelSource, Object.assign({}, T1_ON, settings), args); + try { + return body(assert); + } finally { + cpuSource = originalSource; + cpuBuild = originalBuild; + } + }); +} + +const GL_MODE = GPU.isHeadlessGLSupported ? 'headlessgl' : (GPU.isWebGLSupported ? 'webgl' : null); + +/** + * The emitted source, plus whether the build stayed optimized. A bail row + * asserts that the optimized text equals the un-optimized text, and a + * build-time throw degrades to exactly that text (#868) -- so without the + * second half, a bail that broke badly enough to crash the pass would still + * read as a clean skip. + */ +let cpuBuild = function (kernelSource, settings, args) { + const gpu = new GPU({ mode: 'cpu' }); + try { + const kernel = gpu.createKernel(kernelSource, Object.assign({ output: [4] }, settings)); + kernel.apply(null, args || [[1, 2, 3, 4]]); + return { source: kernel.kernel.kernelString, optimized: !kernel.kernel._optimizerDisabled }; + } finally { + gpu.destroy(); + } +} + +let cpuSource = function (kernelSource, settings, args) { + return cpuBuild(kernelSource, settings, args).source; +} + +function glSource(kernelSource, settings, args) { + const gpu = new GPU({ mode: GL_MODE }); + try { + const kernel = gpu.createKernel(kernelSource, Object.assign({ output: [4] }, settings)); + kernel.apply(null, args || [[1, 2, 3, 4]]); + return kernel.kernel.translatedSource; + } finally { + gpu.destroy(); + } +} + +// Any loop that is not one of the three the cpu backend generates to sweep +// the cells. Matching the user's loop by its counter instead would miss the +// forms whose header the emitter rewrote -- the LOOP_MAX safe wrapping, a +// `var` counter, an assigned rather than declared one -- which are exactly +// the headers the bails below produce. +const cpuLoop = /for \((?!let [xyz] = 0; [xyz] < output)/g; +const glLoop = /for \(/g; + +function count(source, pattern) { + return (source.match(pattern) || []).length; +} + +// ------------------------------------------------------------- T3 unrolling + +const THREE_TRIP = function (a) { + let s = 0; + for (let i = 0; i < 3; i++) { + s += a[i] * 2; + } + return s; +}; + +test('cpu: a literal 3-trip loop becomes three copies of its body', () => { + const optimized = cpuSource(THREE_TRIP); + const disabled = cpuSource(THREE_TRIP, { _optimizerDisabled: true }); + + assert.equal(count(optimized, cpuLoop), 0, 'optimized: no loop is left'); + assert.equal(count(optimized, /user_s\+=/g), 3, 'optimized: the body appears once per iteration'); + assert.notOk(/user_i/.test(optimized), 'optimized: the counter is gone with it'); + assert.ok(/user_a\[0\]/.test(optimized) && /user_a\[1\]/.test(optimized) && /user_a\[2\]/.test(optimized), + 'optimized: each copy reads its own subscript'); + + assert.equal(count(disabled, cpuLoop), 1, 'disabled: the loop is still a loop'); + assert.equal(count(disabled, /user_s\+=/g), 1, 'disabled: one copy of the body'); + assert.ok(/user_a\[user_i\]/.test(disabled), 'disabled: the counter is still a variable'); +}); + +(GL_MODE ? test : skip)('gl: a literal 3-trip loop becomes three copies of its body', () => { + const optimized = glSource(THREE_TRIP); + const disabled = glSource(THREE_TRIP, { _optimizerDisabled: true }); + + assert.equal(count(optimized, glLoop), 0, 'optimized: no loop is left'); + assert.equal(count(optimized, /user_s\+=/g), 3, 'optimized: the body appears once per iteration'); + assert.equal(count(disabled, glLoop), 1, 'disabled: the loop is still a loop'); + assert.equal(count(disabled, /user_s\+=/g), 1, 'disabled: one copy of the body'); +}); + +test('cpu: nested literal loops both go, and multiply out', () => { + const source = cpuSource(function (a) { + let s = 0; + for (let y = 0; y < 2; y++) { + for (let x = 0; x < 3; x++) { + s += a[y][x]; + } + } + return s; + }, {}, [[[1, 2, 3], [4, 5, 6]]]); + + assert.equal(count(source, cpuLoop), 0, 'neither loop is left'); + assert.equal(count(source, /user_s\+=/g), 6, '2 x 3 copies of the body'); + assert.ok(/user_a\[1\]\[2\]/.test(source), 'the last iteration reads a[1][2]'); +}); + +test('cpu: a body local is redeclared per iteration, in its own scope', () => { + const source = cpuSource(function (a) { + let s = 0; + for (let i = 0; i < 3; i++) { + const v = a[i] * 2; + s += v; + } + return s; + }); + assert.equal(count(source, cpuLoop), 0, 'the loop is gone'); + assert.equal(count(source, /const user_v=/g), 3, 'one declaration per iteration'); + assert.equal(count(source, /\{\nconst user_v=/g), 3, 'each one opening a block of its own'); +}); + +// The LOOP_MAX cap only wraps a loop the emitter cannot prove canonical. A +// negative literal init is one such loop on GL -- WebGL1's grammar wants a +// plain literal there -- so the stencil shape every kernel of that family +// uses is emitted as a counted loop with a break. Unrolling deletes the whole +// apparatus, which is the part of T3 that costs the most to give up. +const NEGATIVE_INIT = function (a) { + let s = 0; + for (let dy = -1; dy <= 1; dy++) { + s += a[this.thread.x] * dy; + } + return s; +}; + +(GL_MODE ? test : skip)('gl: an unrolled loop sheds the LOOP_MAX safe wrapping', () => { + const optimized = glSource(NEGATIVE_INIT); + const disabled = glSource(NEGATIVE_INIT, { _optimizerDisabled: true }); + + assert.notOk(/LOOP_MAX/.test(optimized), 'optimized: no iteration cap is emitted'); + assert.notOk(/safeI/.test(optimized), 'optimized: no counter to cap'); + assert.ok(/LOOP_MAX/.test(disabled), 'disabled: the loop is capped'); + assert.ok(/safeI/.test(disabled), 'disabled: with a synthetic counter'); +}); + +// ------------------------------------------------------- the unroll limit + +const NINE_TRIP = function (a) { + let s = 0; + for (let i = 0; i < 9; i++) { + s += a[i % 4]; + } + return s; +}; + +const EIGHT_TRIP = function (a) { + let s = 0; + for (let i = 0; i < 8; i++) { + s += a[i % 4]; + } + return s; +}; + +test('cpu: the limit is inclusive — 8 trips unroll, 9 do not', () => { + const eight = cpuSource(EIGHT_TRIP); + const nine = cpuSource(NINE_TRIP); + assert.equal(count(eight, cpuLoop), 0, 'exactly at the default limit: unrolled'); + assert.equal(count(eight, /user_s\+=/g), 8, 'eight copies'); + assert.equal(count(nine, cpuLoop), 1, 'one past it: left as a loop'); + assert.equal(count(nine, /user_s\+=/g), 1, 'one copy'); +}); + +test('cpu: loopUnrollLimit is the knob', () => { + const raised = cpuSource(NINE_TRIP, { loopUnrollLimit: 16 }); + assert.equal(count(raised, cpuLoop), 0, 'raised past 9: the same loop unrolls'); + assert.equal(count(raised, /user_s\+=/g), 9, 'nine copies'); + + const off = cpuSource(THREE_TRIP, { loopUnrollLimit: 0 }); + assert.equal(count(off, cpuLoop), 1, '0 turns unrolling off'); + assert.equal(count(off, /user_s\+=/g), 1, 'one copy'); +}); + +test('setLoopUnrollLimit reaches the kernel', () => { + const gpu = new GPU({ mode: 'cpu' }); + try { + const kernel = gpu.createKernel(THREE_TRIP, { output: [4] }); + kernel.setLoopUnrollLimit(0); + assert.deepEqual(Array.from(kernel([1, 2, 3, 4])), [12, 12, 12, 12], 'and still computes'); + assert.equal(count(kernel.kernel.kernelString, cpuLoop), 1, 'the loop survived'); + } finally { + gpu.destroy(); + } +}); + +// Every bail asserts the strongest thing available: the optimized text is the +// un-optimized text, character for character. None reads `this.thread` and +// every subscript varies with the counter, so neither of the other two +// transforms can fire and a diff here can only be the unroller. +const BAILS = [ + { + name: 'a break out of the loop', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) { + if (i > n) break; + s += a[i]; + } + return s; + }, + }, + { + name: 'a continue', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) { + if (i === n) continue; + s += a[i]; + } + return s; + }, + }, + { + name: 'a body that assigns the counter', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) { + s += a[i]; + i += n; + } + return s; + }, + }, + { + // the inner block's `i` is a different variable; substituting the + // counter's value through it would rewrite reads of that one + name: 'a nested block that shadows the counter', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 4; i++) { + { + const i = n; + s += a[i % 4]; + } + } + return s; + }, + }, + { + // the generator carries state between draws, and the GL lowering of it is + // chaotic enough that a compiler reassociating one operand by a ULP is a + // different number + name: 'a Math.random draw in the body', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < 3; i++) { + s += Math.random() * a[i] * n; + } + return s; + }, + }, + { + name: 'a non-literal bound', + kernel: function (a, n) { + let s = 0; + for (let i = 0; i < n; i++) { + s += a[i % 4]; + } + return s; + }, + }, + { + name: 'a fractional step', + kernel: function (a, n) { + let s = 0; + for (let t = 0; t < 1; t += 0.25) { + s += a[Math.round(t * 3)] * n; + } + return s; + }, + }, + { + name: 'a counter assigned rather than declared in the header', + kernel: 'function(a, n){let s=0;let i=0;for(i=0;i<4;i++){s+=a[i];}return s+i+n;}', + }, + { + name: 'a function-scoped counter read after the loop', + kernel: 'function(a, n){var s=0;var i=0;for(var i=0;i<4;i++){s+=a[i];}return s+i+n;}', + }, +]; + +for (let b = 0; b < BAILS.length; b++) { + const bail = BAILS[b]; + test(`cpu bail: ${ bail.name }`, () => { + const args = [[1, 2, 3, 4], 2]; + const built = cpuBuild(bail.kernel, { loopMaxIterations: 20 }, args); + const disabled = cpuSource(bail.kernel, { loopMaxIterations: 20, _optimizerDisabled: true }, args); + assert.ok(built.optimized, `${ bail.name }: the optimized build stayed optimized`); + assert.equal(count(built.source, cpuLoop), 1, `${ bail.name }: the loop survived`); + assert.equal(built.source, disabled, `${ bail.name }: emission is unchanged`); + }); +} + +// A name shadowed by an inner scope is the case substitution would get wrong, +// and the two halves of it come out differently -- deliberately. The pass +// unrolls innermost-first, so by the time the outer loop is considered an +// inner loop that unrolled has taken its own counter with it and there is +// nothing left to shadow. One that did NOT unroll still declares the name, +// and the outer loop skips. +test('cpu: an unrollable inner loop takes the shadowing with it', () => { + const source = cpuSource(function (a, n) { + let s = 0; + for (let i = 0; i < 3; i++) { + for (let i = 0; i < 2; i++) { + s += a[i] * n; + } + } + return s; + }, {}, [[1, 2, 3, 4], 2]); + assert.equal(count(source, cpuLoop), 0, 'both loops unroll'); + assert.equal(count(source, /user_a\[0\]/g), 3, 'the inner counter kept its own values'); + assert.equal(count(source, /user_a\[1\]/g), 3, 'both of them, three times over'); + assert.notOk(/user_a\[2\]/.test(source), 'and never took the outer loop\'s'); +}); + +test('cpu bail: an inner loop that keeps the shadowing counter', () => { + const kernel = function (a, n) { + let s = 0; + for (let i = 0; i < 3; i++) { + for (let i = 0; i < n; i++) { + s += a[i % 4]; + } + } + return s; + }; + const built = cpuBuild(kernel, { loopMaxIterations: 20 }, [[1, 2, 3, 4], 2]); + const disabled = cpuSource(kernel, { loopMaxIterations: 20, _optimizerDisabled: true }, [[1, 2, 3, 4], 2]); + assert.ok(built.optimized, 'the optimized build stayed optimized'); + assert.equal(count(built.source, cpuLoop), 2, 'neither loop unrolls'); + assert.equal(built.source, disabled, 'emission is unchanged'); +}); + +test('cpu: a negative counter substitutes as a signed literal, parenthesized', () => { + const built = cpuBuild(function (a) { + let s = 0; + for (let i = -2; i < 2; i++) { + s += a[i + 2] * i + a[1 - i] * 0.5; + } + return s; + }); + assert.ok(built.optimized, 'the optimized build stayed optimized'); + assert.equal(count(built.source, cpuLoop), 0, 'the loop unrolled'); + // `1 - -2` written bare is `1--2`, a decrement + assert.ok(/user_a\[\(1-\(-2\)\)\]/.test(built.source), 'the sign carries its own parentheses'); + assert.notOk(/--/.test(built.source), 'nothing reads as a decrement'); +}); + +// A counter named for a coordinate is the shape that catches a substitution +// walking into a non-computed member's property: `this.thread.x` names `x` +// there as a FIELD, and rewriting it produces `this.thread.0`. +T1_TEST('cpu: a counter named x leaves this.thread.x alone', () => { + const built = cpuBuild(function (a) { + let s = 0; + for (let x = 0; x < 3; x++) { + s += a[x] * this.thread.x; + } + return s; + }); + assert.ok(built.optimized, 'the optimized build stayed optimized'); + assert.equal(count(built.source, cpuLoop), 0, 'the loop unrolled'); + assert.equal(count(built.source, /user_a\[0\]\*x\)/g), 1, 'a[0] times the coordinate'); + assert.equal(count(built.source, /user_a\[2\]\*x\)/g), 1, 'a[2] times the coordinate'); +}); + +// ------------------------------------------------ T1 coordinate localization + +const THREAD_READER = function (a) { + return a[this.thread.x] + this.thread.y + this.thread.z; +}; + +T1_TEST('cpu: thread coordinates become the cell loop\'s own locals', () => { + const optimized = cpuSource(THREAD_READER); + const disabled = cpuSource(THREAD_READER, { _optimizerDisabled: true }); + + assert.notOk(/_this\.thread\./.test(afterCellLoop(optimized)), + 'optimized: no thread property is read in the kernel body'); + assert.ok(/user_a\[x\]/.test(optimized), 'optimized: x is the loop counter'); + assert.ok(/_this\.thread\.x/.test(disabled), 'disabled: the property read stays'); +}); + +// everything before the innermost `this.thread.x = x` is the generated +// preamble, which assigns the thread object and must keep doing so: the +// coordinate is still what `color()` and every helper reads. +function afterCellLoop(source) { + const at = source.lastIndexOf('this.thread.x = x;'); + return at === -1 ? source : source.slice(at + 'this.thread.x = x;'.length); +} + +T1_TEST('cpu: a rank the output does not have localizes to 0', () => { + const oneD = cpuSource(THREAD_READER); + assert.ok(/\+0\)\+0\)/.test(oneD.replace(/\s/g, '')), + `1D: y and z are literal 0 (${ afterCellLoop(oneD).trim().split('\n')[0] })`); + + const threeD = cpuSource(THREAD_READER, { output: [2, 2, 2] }, [[1, 2]]); + const body = afterCellLoop(threeD); + assert.ok(/user_a\[x\]/.test(body), '3D: x is a counter'); + assert.ok(/\+y\)/.test(body.replace(/\s/g, '')), '3D: so is y'); + assert.ok(/\+z\)/.test(body.replace(/\s/g, '')), '3D: so is z'); +}); + +T1_TEST('cpu: a helper keeps the property read, which is all it can reach', () => { + // the call sits in a ternary branch, which is the one position T2 will not + // hoist a call out of -- so the helper survives as a function, which is the + // only way to ask what a helper's coordinate read emits as + const source = cpuSource(function (a) { + return (this.thread.x > 0 ? offset(a) : 0) + this.thread.x; + }, { + functions: [function offset(a) { + return a[this.thread.x] * 2; + }], + }); + assert.ok(/function offset\(user_a\) \{\nreturn \(user_a\[_this\.thread\.x\]\*2\)/.test(source), + 'the helper reads _this.thread.x — the cell loop\'s counters are not in its scope'); + assert.ok(/offset\(user_a\):0\)\+x\)/.test(source.replace(/\s/g, '')), + 'the root body next to it uses the counter'); +}); + +// T1's other half is a claim about what does NOT need doing. +test('cpu: constants and output are already loop-invariant bindings', () => { + const source = cpuSource(function (a) { + return a[this.thread.x] * this.constants.n + this.output.x; + }, { constants: { n: 3 } }); + + assert.ok(/const constants_n = this\.constants\.n;/.test(source), + 'the constant is bound once, above the returned closure'); + assert.ok(/const outputX = _this\.output\[0\];/.test(source), + 'the output size is bound once, above the cell loop'); + const body = afterCellLoop(source); + assert.notOk(/_this\.constants/.test(body), 'neither is re-read per cell'); + assert.notOk(/_this\.output\[/.test(body), 'neither is re-read per cell'); +}); diff --git a/test/internal/backend/web-gl/function-node/getVariableSignature.js b/test/internal/backend/web-gl/function-node/getVariableSignature.js index a1fb5bfd..3e4bee79 100644 --- a/test/internal/backend/web-gl/function-node/getVariableSignature.js +++ b/test/internal/backend/web-gl/function-node/getVariableSignature.js @@ -5,7 +5,10 @@ describe('WebGLFunctionNode.getVariableSignature()'); function run(value) { const mockInstance = { + name: 'mock', source: `function() { ${value}; }`, + getRawAST: WebGLFunctionNode.prototype.getRawAST, + optimizeAST: () => {}, traceFunctionAST: () => {} }; const ast = WebGLFunctionNode.prototype.getJsAST.call(mockInstance); diff --git a/test/internal/deep-types.js b/test/internal/deep-types.js index 5fa1cd43..8fff4b3c 100644 --- a/test/internal/deep-types.js +++ b/test/internal/deep-types.js @@ -4,6 +4,13 @@ const { GPU, FunctionBuilder } = require('../../src'); describe('internal: deep types'); +// Every kernel here is built with the optimizer OFF. What these tests measure +// is the type-resolution machinery -- how many times the builder looks up a +// callee's return type, and for which name -- and T2 answers those questions +// by deleting the call. Inlining's own effect on these shapes is asserted in +// test/features/optimizer. +const OFF = { _optimizerDisabled: true }; + function oneLayerDeepFloat(mode) { const gpu = new GPU({ mode }); function childFunction(childFunctionArgument1) { @@ -13,7 +20,7 @@ function oneLayerDeepFloat(mode) { const kernel = gpu.createKernel(function(kernelArgument1) { return childFunction(kernelArgument1); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(1.5); @@ -48,7 +55,7 @@ function twoLayerDeepFloat(mode) { .addFunction(child2Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(kernelArgument1); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(1.5); @@ -85,7 +92,7 @@ function twoArgumentLayerDeepFloat(mode) { .addFunction(child2Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(child2Function(kernelArgument1)); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(1.5); @@ -128,7 +135,7 @@ function threeLayerDeepFloat(mode) { .addFunction(child3Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(kernelArgument1); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(1.5); @@ -171,7 +178,7 @@ function threeArgumentLayerDeepFloat(mode) { .addFunction(child3Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(child2Function(child3Function(kernelArgument1))); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(1.5); @@ -201,7 +208,7 @@ function threeArgumentLayerDeepNumberTexture1(mode) { const gpu = new GPU({ mode }); const texture = gpu.createKernel(function() { return 1.5; - }, { output: [1], pipeline: true, precision: 'single' })(); + }, { output: [1], pipeline: true, precision: 'single', ...OFF })(); function child1Function(child1FunctionArgument1) { return child1FunctionArgument1 + 1; } @@ -217,7 +224,7 @@ function threeArgumentLayerDeepNumberTexture1(mode) { .addFunction(child3Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(child2Function(child3Function(kernelArgument1))); - }, { output: [1] }); + }, { output: [1], ...OFF }); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); try { const result = kernel(texture); @@ -252,7 +259,7 @@ function circlicalLogic(mode) { .addFunction(child1Function); const kernel = gpu.createKernel(function(kernelArgument1) { return child1Function(kernelArgument1); - }, { output: [1] }); + }, { output: [1], ...OFF }); assert.throws(() => { kernel(1.5); }); @@ -287,7 +294,7 @@ function arrayTexture1(mode) { const kernel = gpu.createKernel(function(kernelValue) { return addOne(kernelValue); - }, { output: [1] }); + }, { output: [1], ...OFF }); const result = kernel(texture1); assert.equal(result[0], 2); gpu.destroy(); @@ -332,7 +339,7 @@ function arrayTexture2(mode) { const kernel = gpu.createKernel(function(kernelValue) { return addOne(kernelValue); - }, { output: [1] }); + }, { output: [1], ...OFF }); const result = kernel(texture1); assert.equal(result[0], 5); gpu.destroy(); @@ -379,7 +386,7 @@ function arrayTexture3(mode) { const kernel = gpu.createKernel(function(kernelValue) { return addOne(kernelValue); - }, { output: [1] }); + }, { output: [1], ...OFF }); const result = kernel(texture1); assert.equal(result[0], 9); gpu.destroy(); @@ -427,7 +434,7 @@ function arrayTexture4(mode) { const kernel = gpu.createKernel(function(kernelValue) { return addOne(kernelValue); - }, { output: [1] }); + }, { output: [1], ...OFF }); const result = kernel(texture1); assert.equal(result[0], 14); gpu.destroy(); @@ -479,7 +486,7 @@ function testTortureTest(mode) { try { const kernel = gpu.createKernel(function (v1, v2, v3, v4, v5) { return addFloatFloat(v4, addArrayFloat(v3, addFloatArray(addArrayArray(v1, v5), v2))); - }, {output: [1]}); + }, {output: [1], ...OFF}); const result = kernel([1], texture, [3], 4, new Float32Array([5])); assert.equal(result[0], 1 + 2 + 3 + 4 + 5); diff --git a/test/internal/function-composition.js b/test/internal/function-composition.js index 0c585475..c40aff6a 100644 --- a/test/internal/function-composition.js +++ b/test/internal/function-composition.js @@ -88,7 +88,10 @@ function numberFunctionCompositionFunctionBuilder(FunctionNode) { kernelArguments: [], kernelConstants: [], output, - leadingReturnStatement: 'resultX[x] = ' + leadingReturnStatement: 'resultX[x] = ', + // the subject here is composition emission: T2 would inline `inner` away, + // which its own suite asserts + _optimizerDisabled: true }, FunctionNode); return builder.getPrototypeString('kernel'); @@ -138,7 +141,10 @@ function array2FunctionCompositionFunctionBuilder(FunctionNode) { kernelArguments: [], kernelConstants: [], output, - leadingReturnStatement: 'resultX[x] = ' + leadingReturnStatement: 'resultX[x] = ', + // the subject here is composition emission: T2 would inline `inner` away, + // which its own suite asserts + _optimizerDisabled: true }, FunctionNode); return builder.getPrototypeString('kernel'); diff --git a/test/internal/wgsl-codegen.js b/test/internal/wgsl-codegen.js index 54ebe489..11d4d478 100644 --- a/test/internal/wgsl-codegen.js +++ b/test/internal/wgsl-codegen.js @@ -97,6 +97,8 @@ test('a helper named after a WGSL builtin keeps its definition', t => { argumentTypes: ['Array'], args: [[1, 2, 3, 4]], functions: [function cross(a, b) { return a * b; }], + // the subject is the mangler; T2 would inline the helper out of existence + _optimizerDisabled: true, }); t.ok(/fn fn_cross\(/.test(wgsl), 'the mangled definition is present'); t.ok(/fn_cross\(/.test(wgsl.split('fn fn_cross')[1] || ''), 'and the call site uses it'); @@ -111,6 +113,7 @@ test('helper argument types still infer through the original name', t => { argumentTypes: ['Array'], args: [[1, 2, 3, 4]], functions: [function cross(a, b) { return a * b; }], + _optimizerDisabled: true, }); t.ok(/fn fn_cross\(user_a : f32, user_b : f32\)/.test(wgsl), 'both parameters typed f32'); }); @@ -155,6 +158,7 @@ test('every user function name is mangled, reserved or not', t => { argumentTypes: ['Array'], args: [[1, 2, 3, 4]], functions: [`function ${ name }(x) { return x * 2; }`], + _optimizerDisabled: true, }); t.ok(new RegExp(`fn fn_${ name }\\(`).test(wgsl), `${ name } definition is mangled`); t.notOk(new RegExp(`\\bfn ${ name }\\(`).test(wgsl), `${ name } never appears bare as a definition`); diff --git a/test/issues/401-cpu-canvas-check.js b/test/issues/401-cpu-canvas-check.js index 42efea53..09450984 100644 --- a/test/issues/401-cpu-canvas-check.js +++ b/test/issues/401-cpu-canvas-check.js @@ -10,6 +10,7 @@ test('Issue #401 - cpu no canvas graphical', function(assert) { setupArguments: function() {}, validateSettings: function() {}, getKernelString: function() {}, + buildWithOptimizer: function(work) { return work(); }, translateSource: function() {}, buildSignature: function() {}, graphical: true, @@ -27,6 +28,7 @@ test('Issue #401 - cpu no canvas', function(assert) { setupArguments: function() {}, validateSettings: function() {}, getKernelString: function() {}, + buildWithOptimizer: function(work) { return work(); }, translateSource: function() {}, buildSignature: function() {}, graphical: false,