From 914bae02ea1db3c29a43b3290ee1d0c194b1abac Mon Sep 17 00:00:00 2001 From: Robert Plummer Date: Thu, 20 Jun 2019 10:11:12 -0400 Subject: [PATCH] fix: #483 Handle and test Int32Array, Int16Array, and Int8Array transfer types feat: Allow for arrow functions as kernels fix: Deep types where the argument contains a function call, and test fix: Only set argument type if it isn't already set fix: Bump version and build fix: Add Sponsorship from browser-stack --- README.md | 3 + bin/gpu-browser-core.js | 46 ++- bin/gpu-browser-core.min.js | 50 ++- bin/gpu-browser.js | 46 ++- bin/gpu-browser.min.js | 50 ++- package.json | 2 +- src/backend/function-builder.js | 11 +- src/backend/function-node.js | 10 +- src/backend/web-gl/function-node.js | 5 +- src/backend/web-gl/kernel-value/index.js | 16 +- test/features/input.js | 34 ++ .../firstAvailableTypeFromAst.js | 34 +- test/internal/deep-types.js | 298 +++++++++++++----- 13 files changed, 472 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index f56a1ebd..c4a5adac 100644 --- a/README.md +++ b/README.md @@ -912,6 +912,9 @@ Support this project by becoming a sponsor. Your logo will show up here with a l ![](https://www.leadergpu.com/assets/main/logo_leadergpu-a8cacac0c90d204b7f7f6c8420c6a149e71ebe53f3f28f3fc94a01cd05c0bd93.png) Sponsored NodeJS GPU environment from [LeaderGPU](https://www.leadergpu.com) - These guys rock! +![](https://3fxtqy18kygf3on3bu39kh93-wpengine.netdna-ssl.com/wp-content/themes/browserstack/img/browserstack-logo.svg) +Sponsored Browser GPU environment's from [BrowserStack](https://i.ibb.co/KbcB3SL/browserstack-logo-600x315.png) - Second to none! + diff --git a/bin/gpu-browser-core.js b/bin/gpu-browser-core.js index 2898775b..6b7de894 100644 --- a/bin/gpu-browser-core.js +++ b/bin/gpu-browser-core.js @@ -4,8 +4,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:12 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:00 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -2021,7 +2021,13 @@ class FunctionBuilder { if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { const args = ast.arguments; for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); } return node.returnType = node.getType(node.getJsAST()); } @@ -2109,7 +2115,10 @@ class FunctionBuilder { assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; - this._getFunction(functionName).argumentTypes[i] = argumentType; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { @@ -2454,7 +2463,11 @@ class FunctionNode { if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { - type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(ast.name, this); + const foundArgumentType = this.lookupArgumentType(ast.name, this); + if (!this.argumentTypes[argumentIndex]) { + this.argumentTypes[argumentIndex] = foundArgumentType; + } + type = foundArgumentType; } } if (!type && this.strictTypingChecking) { @@ -2647,6 +2660,7 @@ class FunctionNode { return this.getLookupType(this.getVariableType(ast.object.object.object)); case 'value[][][][]': return this.getLookupType(this.getVariableType(ast.object.object.object.object)); + case 'value.thread.value': case 'this.thread.value': return 'Integer'; case 'this.output.value': @@ -2930,6 +2944,7 @@ class FunctionNode { 'value[][][]', 'value[][][][]', 'value.value', + 'value.thread.value', 'this.thread.value', 'this.output.value', 'this.constants.value', @@ -3252,6 +3267,7 @@ class FunctionNode { switch (variableSignature) { case 'value': return null; + case 'value.thread.value': case 'this.thread.value': case 'this.output.value': return { @@ -3514,7 +3530,6 @@ const typeLookupMap = { module.exports = { FunctionNode }; - },{"../utils":89,"./function-tracer":10,"acorn":1}],10:[function(require,module,exports){ class FunctionTracer { constructor(ast) { @@ -6975,6 +6990,7 @@ class WebGLFunctionNode extends FunctionNode { zProperty } = this.getMemberExpressionDetails(mNode); switch (signature) { + case 'value.thread.value': case 'this.thread.value': if (name !== 'x' && name !== 'y' && name !== 'z') { throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); @@ -7140,7 +7156,9 @@ class WebGLFunctionNode extends FunctionNode { case 'Array3D': case 'Array4D': case 'Input': - + case 'Number': + case 'Float': + case 'Integer': if (this.precision === 'single') { retArr.push(`getMemoryOptimized32(${markupName}, ${markupName}Size, ${markupName}Dim, `); this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); @@ -7849,9 +7867,21 @@ class WebGLKernelValue extends KernelValue { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } - if (value.constructor === Array) { - return Float32Array; + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); return value.constructor; } formatArrayTransfer(value, length, Type) { diff --git a/bin/gpu-browser-core.min.js b/bin/gpu-browser-core.min.js index 093d0d75..972823d8 100644 --- a/bin/gpu-browser-core.min.js +++ b/bin/gpu-browser-core.min.js @@ -4,8 +4,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:14 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:02 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -17,8 +17,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:12 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:00 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -2034,7 +2034,13 @@ class FunctionBuilder { if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { const args = ast.arguments; for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); } return node.returnType = node.getType(node.getJsAST()); } @@ -2122,7 +2128,10 @@ class FunctionBuilder { assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; - this._getFunction(functionName).argumentTypes[i] = argumentType; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { @@ -2467,7 +2476,11 @@ class FunctionNode { if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { - type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(ast.name, this); + const foundArgumentType = this.lookupArgumentType(ast.name, this); + if (!this.argumentTypes[argumentIndex]) { + this.argumentTypes[argumentIndex] = foundArgumentType; + } + type = foundArgumentType; } } if (!type && this.strictTypingChecking) { @@ -2660,6 +2673,7 @@ class FunctionNode { return this.getLookupType(this.getVariableType(ast.object.object.object)); case 'value[][][][]': return this.getLookupType(this.getVariableType(ast.object.object.object.object)); + case 'value.thread.value': case 'this.thread.value': return 'Integer'; case 'this.output.value': @@ -2943,6 +2957,7 @@ class FunctionNode { 'value[][][]', 'value[][][][]', 'value.value', + 'value.thread.value', 'this.thread.value', 'this.output.value', 'this.constants.value', @@ -3265,6 +3280,7 @@ class FunctionNode { switch (variableSignature) { case 'value': return null; + case 'value.thread.value': case 'this.thread.value': case 'this.output.value': return { @@ -3527,7 +3543,6 @@ const typeLookupMap = { module.exports = { FunctionNode }; - },{"../utils":89,"./function-tracer":10,"acorn":1}],10:[function(require,module,exports){ class FunctionTracer { constructor(ast) { @@ -6988,6 +7003,7 @@ class WebGLFunctionNode extends FunctionNode { zProperty } = this.getMemberExpressionDetails(mNode); switch (signature) { + case 'value.thread.value': case 'this.thread.value': if (name !== 'x' && name !== 'y' && name !== 'z') { throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); @@ -7153,7 +7169,9 @@ class WebGLFunctionNode extends FunctionNode { case 'Array3D': case 'Array4D': case 'Input': - + case 'Number': + case 'Float': + case 'Integer': if (this.precision === 'single') { retArr.push(`getMemoryOptimized32(${markupName}, ${markupName}Size, ${markupName}Dim, `); this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); @@ -7862,9 +7880,21 @@ class WebGLKernelValue extends KernelValue { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } - if (value.constructor === Array) { - return Float32Array; + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); return value.constructor; } formatArrayTransfer(value, length, Type) { diff --git a/bin/gpu-browser.js b/bin/gpu-browser.js index d2b8553e..fcbc14b6 100644 --- a/bin/gpu-browser.js +++ b/bin/gpu-browser.js @@ -4,8 +4,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:12 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:00 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -6785,7 +6785,13 @@ class FunctionBuilder { if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { const args = ast.arguments; for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); } return node.returnType = node.getType(node.getJsAST()); } @@ -6873,7 +6879,10 @@ class FunctionBuilder { assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; - this._getFunction(functionName).argumentTypes[i] = argumentType; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { @@ -7218,7 +7227,11 @@ class FunctionNode { if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { - type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(ast.name, this); + const foundArgumentType = this.lookupArgumentType(ast.name, this); + if (!this.argumentTypes[argumentIndex]) { + this.argumentTypes[argumentIndex] = foundArgumentType; + } + type = foundArgumentType; } } if (!type && this.strictTypingChecking) { @@ -7411,6 +7424,7 @@ class FunctionNode { return this.getLookupType(this.getVariableType(ast.object.object.object)); case 'value[][][][]': return this.getLookupType(this.getVariableType(ast.object.object.object.object)); + case 'value.thread.value': case 'this.thread.value': return 'Integer'; case 'this.output.value': @@ -7694,6 +7708,7 @@ class FunctionNode { 'value[][][]', 'value[][][][]', 'value.value', + 'value.thread.value', 'this.thread.value', 'this.output.value', 'this.constants.value', @@ -8016,6 +8031,7 @@ class FunctionNode { switch (variableSignature) { case 'value': return null; + case 'value.thread.value': case 'this.thread.value': case 'this.output.value': return { @@ -8278,7 +8294,6 @@ const typeLookupMap = { module.exports = { FunctionNode }; - },{"../utils":90,"./function-tracer":11,"acorn":1}],11:[function(require,module,exports){ class FunctionTracer { constructor(ast) { @@ -11739,6 +11754,7 @@ class WebGLFunctionNode extends FunctionNode { zProperty } = this.getMemberExpressionDetails(mNode); switch (signature) { + case 'value.thread.value': case 'this.thread.value': if (name !== 'x' && name !== 'y' && name !== 'z') { throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); @@ -11904,7 +11920,9 @@ class WebGLFunctionNode extends FunctionNode { case 'Array3D': case 'Array4D': case 'Input': - + case 'Number': + case 'Float': + case 'Integer': if (this.precision === 'single') { retArr.push(`getMemoryOptimized32(${markupName}, ${markupName}Size, ${markupName}Dim, `); this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); @@ -12613,9 +12631,21 @@ class WebGLKernelValue extends KernelValue { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } - if (value.constructor === Array) { - return Float32Array; + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); return value.constructor; } formatArrayTransfer(value, length, Type) { diff --git a/bin/gpu-browser.min.js b/bin/gpu-browser.min.js index 7e679951..cbc7373d 100644 --- a/bin/gpu-browser.min.js +++ b/bin/gpu-browser.min.js @@ -4,8 +4,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:14 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:02 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -17,8 +17,8 @@ * * GPU Accelerated JavaScript * - * @version 2.0.0-rc.15 - * @date Mon Jun 17 2019 18:00:12 GMT-0400 (Eastern Daylight Time) + * @version 2.0.0-rc.16 + * @date Thu Jun 20 2019 10:09:00 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -6798,7 +6798,13 @@ class FunctionBuilder { if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { const args = ast.arguments; for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); } return node.returnType = node.getType(node.getJsAST()); } @@ -6886,7 +6892,10 @@ class FunctionBuilder { assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; - this._getFunction(functionName).argumentTypes[i] = argumentType; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { @@ -7231,7 +7240,11 @@ class FunctionNode { if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { - type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(ast.name, this); + const foundArgumentType = this.lookupArgumentType(ast.name, this); + if (!this.argumentTypes[argumentIndex]) { + this.argumentTypes[argumentIndex] = foundArgumentType; + } + type = foundArgumentType; } } if (!type && this.strictTypingChecking) { @@ -7424,6 +7437,7 @@ class FunctionNode { return this.getLookupType(this.getVariableType(ast.object.object.object)); case 'value[][][][]': return this.getLookupType(this.getVariableType(ast.object.object.object.object)); + case 'value.thread.value': case 'this.thread.value': return 'Integer'; case 'this.output.value': @@ -7707,6 +7721,7 @@ class FunctionNode { 'value[][][]', 'value[][][][]', 'value.value', + 'value.thread.value', 'this.thread.value', 'this.output.value', 'this.constants.value', @@ -8029,6 +8044,7 @@ class FunctionNode { switch (variableSignature) { case 'value': return null; + case 'value.thread.value': case 'this.thread.value': case 'this.output.value': return { @@ -8291,7 +8307,6 @@ const typeLookupMap = { module.exports = { FunctionNode }; - },{"../utils":90,"./function-tracer":11,"acorn":1}],11:[function(require,module,exports){ class FunctionTracer { constructor(ast) { @@ -11752,6 +11767,7 @@ class WebGLFunctionNode extends FunctionNode { zProperty } = this.getMemberExpressionDetails(mNode); switch (signature) { + case 'value.thread.value': case 'this.thread.value': if (name !== 'x' && name !== 'y' && name !== 'z') { throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); @@ -11917,7 +11933,9 @@ class WebGLFunctionNode extends FunctionNode { case 'Array3D': case 'Array4D': case 'Input': - + case 'Number': + case 'Float': + case 'Integer': if (this.precision === 'single') { retArr.push(`getMemoryOptimized32(${markupName}, ${markupName}Size, ${markupName}Dim, `); this.memberExpressionXYZ(xProperty, yProperty, zProperty, retArr); @@ -12626,9 +12644,21 @@ class WebGLKernelValue extends KernelValue { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } - if (value.constructor === Array) { - return Float32Array; + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); return value.constructor; } formatArrayTransfer(value, length, Type) { diff --git a/package.json b/package.json index 83508415..7b37d2e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gpu.js", - "version": "2.0.0-rc.15", + "version": "2.0.0-rc.16", "description": "GPU Accelerated JavaScript", "engines": { "node": ">=10.0.0" diff --git a/src/backend/function-builder.js b/src/backend/function-builder.js index 8c34f76d..5e3d3fc2 100644 --- a/src/backend/function-builder.js +++ b/src/backend/function-builder.js @@ -436,7 +436,13 @@ class FunctionBuilder { if (node.argumentTypes.length === 0 && ast.arguments.length > 0) { const args = ast.arguments; for (let j = 0; j < args.length; j++) { + this.lookupChain.push({ + name: requestingNode.name, + ast: args[i], + requestingNode + }); node.argumentTypes[j] = requestingNode.getType(args[j]); + this.lookupChain.pop(); } return node.returnType = node.getType(node.getJsAST()); } @@ -526,7 +532,10 @@ class FunctionBuilder { assignArgumentType(functionName, i, argumentType, requestingNode) { if (!this._isFunction(functionName)) return; - this._getFunction(functionName).argumentTypes[i] = argumentType; + const fnNode = this._getFunction(functionName); + if (!fnNode.argumentTypes[i]) { + fnNode.argumentTypes[i] = argumentType; + } } trackArgumentSynonym(functionName, argumentName, calleeFunctionName, argumentIndex) { diff --git a/src/backend/function-node.js b/src/backend/function-node.js index 429489f1..2d6fc6fb 100644 --- a/src/backend/function-node.js +++ b/src/backend/function-node.js @@ -303,7 +303,12 @@ class FunctionNode { if (argumentType) { type = argumentType; } else if (this.lookupArgumentType) { - type = this.argumentTypes[argumentIndex] = this.lookupArgumentType(ast.name, this); + const foundArgumentType = this.lookupArgumentType(ast.name, this); + // argumentType may be filled in by now + if (!this.argumentTypes[argumentIndex]) { + this.argumentTypes[argumentIndex] = foundArgumentType; + } + type = foundArgumentType; } } if (!type && this.strictTypingChecking) { @@ -514,6 +519,7 @@ class FunctionNode { return this.getLookupType(this.getVariableType(ast.object.object.object)); case 'value[][][][]': return this.getLookupType(this.getVariableType(ast.object.object.object.object)); + case 'value.thread.value': case 'this.thread.value': return 'Integer'; case 'this.output.value': @@ -804,6 +810,7 @@ class FunctionNode { 'value[][][]', 'value[][][][]', 'value.value', + 'value.thread.value', 'this.thread.value', 'this.output.value', 'this.constants.value', @@ -1210,6 +1217,7 @@ class FunctionNode { switch (variableSignature) { case 'value': return null; + case 'value.thread.value': case 'this.thread.value': case 'this.output.value': return { diff --git a/src/backend/web-gl/function-node.js b/src/backend/web-gl/function-node.js index 855e6bfa..699d0b40 100644 --- a/src/backend/web-gl/function-node.js +++ b/src/backend/web-gl/function-node.js @@ -997,6 +997,7 @@ class WebGLFunctionNode extends FunctionNode { zProperty } = this.getMemberExpressionDetails(mNode); switch (signature) { + case 'value.thread.value': case 'this.thread.value': if (name !== 'x' && name !== 'y' && name !== 'z') { throw this.astErrorOutput('Unexpected expression, expected `this.thread.x`, `this.thread.y`, or `this.thread.z`', mNode); @@ -1166,7 +1167,9 @@ class WebGLFunctionNode extends FunctionNode { case 'Array3D': case 'Array4D': case 'Input': - + case 'Number': + case 'Float': + case 'Integer': if (this.precision === 'single') { // bitRatio is always 4 here, javascript doesn't yet have 8 or 16 bit support // TODO: make 8 or 16 bit work anyway! diff --git a/src/backend/web-gl/kernel-value/index.js b/src/backend/web-gl/kernel-value/index.js index acd90b6a..e1965679 100644 --- a/src/backend/web-gl/kernel-value/index.js +++ b/src/backend/web-gl/kernel-value/index.js @@ -35,9 +35,21 @@ class WebGLKernelValue extends KernelValue { if (Array.isArray(value[0])) { return this.getTransferArrayType(value[0]); } - if (value.constructor === Array) { - return Float32Array; + switch (value.constructor) { + case Array: + case Int32Array: + case Int16Array: + case Int8Array: + return Float32Array; + case Uint8ClampedArray: + case Uint8Array: + case Uint16Array: + case Uint32Array: + case Float32Array: + case Float64Array: + return value.constructor; } + console.warn('Unfamiliar constructor type. Will go ahead and use, but likley this may result in a transfer of zeros'); return value.constructor; } /** diff --git a/test/features/input.js b/test/features/input.js index bb3de36c..2f6dcd17 100644 --- a/test/features/input.js +++ b/test/features/input.js @@ -278,3 +278,37 @@ test("inputZYXVariables gpu", () => { test("inputZYXVariables cpu", () => { inputZYXVariables('cpu'); }); + +function inputInt32ArrayX(mode) { + const gpu = new GPU({ mode }); + const kernel = gpu.createKernel(function(a) { + return a[this.thread.x]; + }) + .setPrecision('unsigned') + .setOutput([9]); + + const a = new Int32Array([1,2,3,4,5,6,7,8,9]); + const result = kernel(input(a, [3, 3])); + assert.deepEqual(result, new Float32Array([1,2,3,4,5,6,7,8,9])); + gpu.destroy(); +} + +test("inputInt32ArrayX auto", () => { + inputInt32ArrayX(); +}); + +test("inputInt32ArrayX gpu", () => { + inputInt32ArrayX('gpu'); +}); + +(GPU.isWebGLSupported ? test : skip)("inputInt32ArrayX webgl", () => { + inputInt32ArrayX('webgl'); +}); + +(GPU.isWebGL2Supported ? test : skip)("inputInt32ArrayX webgl2", () => { + inputInt32ArrayX('webgl2'); +}); + +test("inputInt32ArrayX cpu", () => { + inputInt32ArrayX('cpu'); +}); diff --git a/test/internal/backend/web-gl/function-node/firstAvailableTypeFromAst.js b/test/internal/backend/web-gl/function-node/firstAvailableTypeFromAst.js index 53a8420f..b0f37797 100644 --- a/test/internal/backend/web-gl/function-node/firstAvailableTypeFromAst.js +++ b/test/internal/backend/web-gl/function-node/firstAvailableTypeFromAst.js @@ -194,69 +194,69 @@ test('Math.LOG10E', () => { }); test('Math.abs(value)', () => { - assert.equal(run('Math.abs(value)'), 'Number'); + assert.equal(run('Math.abs(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.acos(value)', () => { - assert.equal(run('Math.acos(value)'), 'Number'); + assert.equal(run('Math.acos(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.atan(value)', () => { - assert.equal(run('Math.atan(value)'), 'Number'); + assert.equal(run('Math.atan(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.atan2(value, value2)', () => { - assert.equal(run('Math.atan2(value, value2)'), 'Number'); + assert.equal(run('Math.atan2(value, value2)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.ceil(value)', () => { - assert.equal(run('Math.ceil(value)'), 'Number'); + assert.equal(run('Math.ceil(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.cos(value)', () => { - assert.equal(run('Math.cos(value)'), 'Number'); + assert.equal(run('Math.cos(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.exp(value)', () => { - assert.equal(run('Math.exp(value)'), 'Number'); + assert.equal(run('Math.exp(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.floor(value)', () => { - assert.equal(run('Math.floor(value)'), 'Number'); + assert.equal(run('Math.floor(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.log(value)', () => { - assert.equal(run('Math.log(value)'), 'Number'); + assert.equal(run('Math.log(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.max(value, value2, value3)', () => { - assert.equal(run('Math.max(value, value2, value3)'), 'Number'); + assert.equal(run('Math.max(value, value2, value3)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.min(value, value2, value3)', () => { - assert.equal(run('Math.min(value, value2, value3)'), 'Number'); + assert.equal(run('Math.min(value, value2, value3)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.pow(value, value2)', () => { - assert.equal(run('Math.pow(value, value2)'), 'Number'); + assert.equal(run('Math.pow(value, value2)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.random()', () => { - assert.equal(run('Math.random()'), 'Number'); + assert.equal(run('Math.random()', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.round(value)', () => { - assert.equal(run('Math.random(value)'), 'Number'); + assert.equal(run('Math.random(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.sin(value)', () => { - assert.equal(run('Math.sin(value)'), 'Number'); + assert.equal(run('Math.sin(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.sqrt(value)', () => { - assert.equal(run('Math.sqrt(value)'), 'Number'); + assert.equal(run('Math.sqrt(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); test('Math.tan(value)', () => { - assert.equal(run('Math.tan(value)'), 'Number'); + assert.equal(run('Math.tan(value)', { argumentTypes: ['Number', 'Number', 'Number'] }), 'Number'); }); diff --git a/test/internal/deep-types.js b/test/internal/deep-types.js index 0a35a2f8..c17d1fdd 100644 --- a/test/internal/deep-types.js +++ b/test/internal/deep-types.js @@ -16,17 +16,19 @@ function oneLayerDeepFloat(mode) { }, { output: [1] }); sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); - const result = kernel(1.5); - assert.equal(result[0], 2.5); - - assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 1); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'childFunctionArgument1'); - - assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 1); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'childFunction'); - - FunctionBuilder.prototype.lookupArgumentType.restore(); - FunctionBuilder.prototype.lookupReturnType.restore(); + try { + const result = kernel(1.5); + assert.equal(result[0], 2.5); + + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 1); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'childFunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 1); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'childFunction'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } } (GPU.isWebGLSupported ? test : skip)('one layer deep float WebGL', () => { @@ -55,19 +57,21 @@ function twoLayerDeepFloat(mode) { }, { output: [1] }); sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); - const result = kernel(1.5); - assert.equal(result[0], 2.5); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 2); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child2FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child1FunctionArgument1'); - - assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 3); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); - - FunctionBuilder.prototype.lookupArgumentType.restore(); - FunctionBuilder.prototype.lookupReturnType.restore(); + try { + const result = kernel(1.5); + assert.equal(result[0], 2.5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 2); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child2FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child1FunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 3); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } } (GPU.isWebGLSupported ? test : skip)('two layer deep float WebGL', () => { @@ -96,21 +100,23 @@ function twoArgumentLayerDeepFloat(mode) { }, { output: [1] }); sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); - const result = kernel(1.5); - assert.equal(kernel.returnType, 'Float'); - assert.equal(result[0], 3.5); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 2); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child1FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); - - assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 4); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child2Function'); - - FunctionBuilder.prototype.lookupArgumentType.restore(); - FunctionBuilder.prototype.lookupReturnType.restore(); + try { + const result = kernel(1.5); + assert.equal(kernel.returnType, 'Float'); + assert.equal(result[0], 3.5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 2); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child1FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 4); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child2Function'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } } (GPU.isWebGLSupported ? test : skip)('two argument layer deep float WebGL', () => { @@ -144,22 +150,24 @@ function threeLayerDeepFloat(mode) { }, { output: [1] }); sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); - const result = kernel(1.5); - assert.equal(result[0], 3.5); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 3); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child3FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'child1FunctionArgument1'); - - assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 5); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child3Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'child3Function'); - - FunctionBuilder.prototype.lookupArgumentType.restore(); - FunctionBuilder.prototype.lookupReturnType.restore(); + try { + const result = kernel(1.5); + assert.equal(result[0], 3.5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 3); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child3FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'child1FunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 5); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child3Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'child3Function'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } } (GPU.isWebGLSupported ? test : skip)('three layer deep float WebGL', () => { @@ -192,25 +200,26 @@ function threeArgumentLayerDeepFloat(mode) { }, { output: [1] }); sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); - const result = kernel(1.5); - assert.equal(result[0], 4.5); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 3); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child1FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); - assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'child3FunctionArgument1'); - - assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 8); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child3Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[5][0], 'child3Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[6][0], 'child2Function'); - assert.equal(FunctionBuilder.prototype.lookupReturnType.args[7][0], 'child3Function'); - - FunctionBuilder.prototype.lookupArgumentType.restore(); - FunctionBuilder.prototype.lookupReturnType.restore(); + try { + const result = kernel(1.5); + assert.equal(result[0], 4.5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 3); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child1FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'child3FunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 7); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child3Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'child3Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[5][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[6][0], 'child3Function'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } } (GPU.isWebGLSupported ? test : skip)('three argument layer deep float WebGL', () => { @@ -223,6 +232,61 @@ function threeArgumentLayerDeepFloat(mode) { threeArgumentLayerDeepFloat('headlessgl'); }); +function threeArgumentLayerDeepNumberTexture1(mode) { + const gpu = new GPU({ mode }); + const texture = gpu.createKernel(function() { + return 1.5; + }, { output: [1], pipeline: true, precision: 'single' })(); + function child1Function(child1FunctionArgument1) { + return child1FunctionArgument1 + 1; + } + function child2Function(child2FunctionArgument1) { + return child2FunctionArgument1 + 1; + } + function child3Function(child3FunctionArgument1) { + return child3FunctionArgument1[this.thread.x] + 1; + } + gpu + .addFunction(child1Function) + .addFunction(child2Function) + .addFunction(child3Function); + const kernel = gpu.createKernel(function(kernelArgument1) { + return child1Function(child2Function(child3Function(kernelArgument1))); + }, { output: [1] }); + sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); + sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); + try { + const result = kernel(texture); + assert.equal(result[0], 4.5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 3); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'child1FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'child2FunctionArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'child3FunctionArgument1'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 7); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'child1Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'child3Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'child3Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[5][0], 'child2Function'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[6][0], 'child3Function'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } +} + +(GPU.isSinglePrecisionSupported && GPU.isWebGLSupported ? test : skip)('three argument layer deep NumberTexture(1) WebGL', () => { + threeArgumentLayerDeepNumberTexture1('webgl'); +}); +(GPU.isSinglePrecisionSupported && GPU.isWebGL2Supported ? test : skip)('three argument layer deep NumberTexture(1) WebGL2', () => { + threeArgumentLayerDeepNumberTexture1('webgl2'); +}); +(GPU.isSinglePrecisionSupported && GPU.isHeadlessGLSupported ? test : skip)('three argument layer deep NumberTexture(1) HeadlessGL', () => { + threeArgumentLayerDeepNumberTexture1('headlessgl'); +}); + function circlicalLogic(mode) { const gpu = new GPU({ mode }); function child1Function(child1FunctionArgument1) { @@ -431,3 +495,89 @@ function arrayTexture4(mode) { (GPU.isSinglePrecisionSupported ? test : skip)('ArrayTexture(4) cpu', ()=> { arrayTexture4('cpu'); }); + +function testTortureTest(mode) { + const gpu = new GPU({ mode }); + function addFloatArray(addFloatArrayArgument1, addFloatArrayArgument2) { + return addFloatArrayArgument1 + addFloatArrayArgument2[this.thread.x]; + } + function addArrayFloat(addArrayFloatArgument1, addArrayFloatArgument2) { + return addArrayFloatArgument1[this.thread.x] + addArrayFloatArgument2; + } + function addArrayArray(addArrayArrayArgument1, addArrayArrayArgument2) { + return addArrayArrayArgument1[this.thread.x] + addArrayArrayArgument2[this.thread.x]; + } + function addFloatFloat(addFloatFloatArgument1, addFloatFloatArgument2) { + return addFloatFloatArgument1 + addFloatFloatArgument2; + } + gpu + .addFunction(addFloatArray) + .addFunction(addArrayFloat) + .addFunction(addArrayArray) + .addFunction(addFloatFloat); + + const texture = gpu.createKernel(function() { return 2; }, { output: [1], precision: 'single' })(); + sinon.spy(FunctionBuilder.prototype, 'lookupArgumentType'); + sinon.spy(FunctionBuilder.prototype, 'lookupReturnType'); + + try { + const kernel = gpu.createKernel(function (v1, v2, v3, v4, v5) { + return addFloatFloat(v4, addArrayFloat(v3, addFloatArray(addArrayArray(v1, v5), v2))); + }, {output: [1]}); + + const result = kernel([1], texture, [3], 4, new Float32Array([5])); + assert.equal(result[0], 1 + 2 + 3 + 4 + 5); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.callCount, 4); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.returnValues.length, 4); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[0][0], 'addFloatFloatArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.returnValues[0], 'Float'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[1][0], 'addArrayFloatArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.returnValues[1], 'Array'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[2][0], 'addFloatArrayArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.returnValues[2], 'Number'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.args[3][0], 'addArrayArrayArgument1'); + assert.equal(FunctionBuilder.prototype.lookupArgumentType.returnValues[3], 'Number'); + + assert.equal(FunctionBuilder.prototype.lookupReturnType.callCount, 6); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues.length, 6); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[0][0], 'addFloatFloat'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[0], 'Float'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[1][0], 'addArrayFloat'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[1], 'Number'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[2][0], 'addFloatArray'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[2], 'Number'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[3][0], 'addArrayArray'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[3], 'Number'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[4][0], 'addArrayArray'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[4], 'Number'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.args[5][0], 'addArrayArray'); + assert.equal(FunctionBuilder.prototype.lookupReturnType.returnValues[5], 'Number'); + } finally { + FunctionBuilder.prototype.lookupArgumentType.restore(); + FunctionBuilder.prototype.lookupReturnType.restore(); + } +} + +(GPU.isSinglePrecisionSupported ? test : skip)('torture test auto', () => { + testTortureTest(); +}); + +(GPU.isSinglePrecisionSupported ? test : skip)('torture test gpu', () => { + testTortureTest('gpu'); +}); + +(GPU.isSinglePrecisionSupported && GPU.isWebGLSupported ? test : skip)('torture test webgl', () => { + testTortureTest('webgl'); +}); + +(GPU.isSinglePrecisionSupported && GPU.isWebGL2Supported ? test : skip)('torture test webgl2', () => { + testTortureTest('webgl2'); +}); + +(GPU.isSinglePrecisionSupported && GPU.isHeadlessGLSupported ? test : skip)('torture test headlessgl', () => { + testTortureTest('headlessgl'); +}); + +test('torture test cpu', () => { + testTortureTest('cpu'); +});