diff --git a/bin/gpu-browser-core.js b/bin/gpu-browser-core.js index 0259b695..0e9d02ce 100644 --- a/bin/gpu-browser-core.js +++ b/bin/gpu-browser-core.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:22 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:45 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -4581,7 +4581,6 @@ class HeadlessGLKernel extends WebGLKernel { module.exports = { HeadlessGLKernel }; - },{"../gl/kernel-string":10,"../web-gl/kernel":55,"gl":2}],32:[function(require,module,exports){ const { utils } = require('../utils'); @@ -4785,10 +4784,12 @@ class Kernel { setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; - this.argumentTypes = []; - for (let i = 0; i < args.length; i++) { - const argType = utils.getVariableType(args[i], this.strictIntegers); - this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + } } } @@ -6405,7 +6406,6 @@ const operatorMap = { module.exports = { WebGLFunctionNode }; - },{"../function-node":9}],36:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); const { WebGLKernelValueFloat } = require('./kernel-value/float'); @@ -7548,7 +7548,10 @@ class WebGLKernel extends GLKernel { setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; - this.argumentTypes = []; + const needsArgumentTypes = this.argumentTypes === null; + if (needsArgumentTypes) { + this.argumentTypes = []; + } this.argumentSizes = []; this.argumentBitRatios = []; if (!this.precision) { @@ -7565,8 +7568,13 @@ class WebGLKernel extends GLKernel { for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; - const type = utils.getVariableType(value, this.strictIntegers); - this.argumentTypes.push(type); + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); @@ -9990,6 +9998,10 @@ class GPU { source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, @@ -10046,7 +10058,7 @@ class GPU { return newKernel.renderOutput(); } } - }, upgradeDeprecatedCreateKernelSettings(settings) || {}); + }, settingsCopy); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); @@ -10079,7 +10091,12 @@ class GPU { } } - const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + const kernel = this.createKernel(fn, settingsCopy); + if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { @@ -10194,6 +10211,7 @@ module.exports = { kernelOrder, kernelTypes }; + },{"./backend/cpu/kernel":7,"./backend/headless-gl/kernel":31,"./backend/web-gl/kernel":55,"./backend/web-gl2/kernel":79,"./kernel-run-shortcut":85,"./utils":88,"gpu-mock.js":3}],83:[function(require,module,exports){ const { GPU } = require('./gpu'); const { alias } = require('./alias'); diff --git a/bin/gpu-browser-core.min.js b/bin/gpu-browser-core.min.js index de7ff3f7..4da815e5 100644 --- a/bin/gpu-browser-core.min.js +++ b/bin/gpu-browser-core.min.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:24 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:47 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -18,7 +18,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:22 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:45 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -4594,7 +4594,6 @@ class HeadlessGLKernel extends WebGLKernel { module.exports = { HeadlessGLKernel }; - },{"../gl/kernel-string":10,"../web-gl/kernel":55,"gl":2}],32:[function(require,module,exports){ const { utils } = require('../utils'); @@ -4798,10 +4797,12 @@ class Kernel { setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; - this.argumentTypes = []; - for (let i = 0; i < args.length; i++) { - const argType = utils.getVariableType(args[i], this.strictIntegers); - this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + } } } @@ -6418,7 +6419,6 @@ const operatorMap = { module.exports = { WebGLFunctionNode }; - },{"../function-node":9}],36:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); const { WebGLKernelValueFloat } = require('./kernel-value/float'); @@ -7561,7 +7561,10 @@ class WebGLKernel extends GLKernel { setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; - this.argumentTypes = []; + const needsArgumentTypes = this.argumentTypes === null; + if (needsArgumentTypes) { + this.argumentTypes = []; + } this.argumentSizes = []; this.argumentBitRatios = []; if (!this.precision) { @@ -7578,8 +7581,13 @@ class WebGLKernel extends GLKernel { for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; - const type = utils.getVariableType(value, this.strictIntegers); - this.argumentTypes.push(type); + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); @@ -10003,6 +10011,10 @@ class GPU { source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, @@ -10059,7 +10071,7 @@ class GPU { return newKernel.renderOutput(); } } - }, upgradeDeprecatedCreateKernelSettings(settings) || {}); + }, settingsCopy); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); @@ -10092,7 +10104,12 @@ class GPU { } } - const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + const kernel = this.createKernel(fn, settingsCopy); + if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { @@ -10207,6 +10224,7 @@ module.exports = { kernelOrder, kernelTypes }; + },{"./backend/cpu/kernel":7,"./backend/headless-gl/kernel":31,"./backend/web-gl/kernel":55,"./backend/web-gl2/kernel":79,"./kernel-run-shortcut":85,"./utils":88,"gpu-mock.js":3}],83:[function(require,module,exports){ const { GPU } = require('./gpu'); const { alias } = require('./alias'); diff --git a/bin/gpu-browser.js b/bin/gpu-browser.js index d4daa0b3..1acffd9d 100644 --- a/bin/gpu-browser.js +++ b/bin/gpu-browser.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:22 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:45 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -9345,7 +9345,6 @@ class HeadlessGLKernel extends WebGLKernel { module.exports = { HeadlessGLKernel }; - },{"../gl/kernel-string":11,"../web-gl/kernel":56,"gl":3}],33:[function(require,module,exports){ const { utils } = require('../utils'); @@ -9549,10 +9548,12 @@ class Kernel { setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; - this.argumentTypes = []; - for (let i = 0; i < args.length; i++) { - const argType = utils.getVariableType(args[i], this.strictIntegers); - this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + } } } @@ -11169,7 +11170,6 @@ const operatorMap = { module.exports = { WebGLFunctionNode }; - },{"../function-node":10}],37:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); const { WebGLKernelValueFloat } = require('./kernel-value/float'); @@ -12312,7 +12312,10 @@ class WebGLKernel extends GLKernel { setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; - this.argumentTypes = []; + const needsArgumentTypes = this.argumentTypes === null; + if (needsArgumentTypes) { + this.argumentTypes = []; + } this.argumentSizes = []; this.argumentBitRatios = []; if (!this.precision) { @@ -12329,8 +12332,13 @@ class WebGLKernel extends GLKernel { for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; - const type = utils.getVariableType(value, this.strictIntegers); - this.argumentTypes.push(type); + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); @@ -14754,6 +14762,10 @@ class GPU { source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, @@ -14810,7 +14822,7 @@ class GPU { return newKernel.renderOutput(); } } - }, upgradeDeprecatedCreateKernelSettings(settings) || {}); + }, settingsCopy); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); @@ -14843,7 +14855,12 @@ class GPU { } } - const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + const kernel = this.createKernel(fn, settingsCopy); + if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { @@ -14958,6 +14975,7 @@ module.exports = { kernelOrder, kernelTypes }; + },{"./backend/cpu/kernel":8,"./backend/headless-gl/kernel":32,"./backend/web-gl/kernel":56,"./backend/web-gl2/kernel":80,"./kernel-run-shortcut":86,"./utils":89,"gpu-mock.js":4}],84:[function(require,module,exports){ const { GPU } = require('./gpu'); const { alias } = require('./alias'); diff --git a/bin/gpu-browser.min.js b/bin/gpu-browser.min.js index 25a9c5c2..d9e91c1d 100644 --- a/bin/gpu-browser.min.js +++ b/bin/gpu-browser.min.js @@ -5,7 +5,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:24 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:47 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -18,7 +18,7 @@ * GPU Accelerated JavaScript * * @version 2.0.0-rc.14 - * @date Thu May 23 2019 20:48:22 GMT-0400 (Eastern Daylight Time) + * @date Thu May 23 2019 21:45:45 GMT-0400 (Eastern Daylight Time) * * @license MIT * The MIT License @@ -9358,7 +9358,6 @@ class HeadlessGLKernel extends WebGLKernel { module.exports = { HeadlessGLKernel }; - },{"../gl/kernel-string":11,"../web-gl/kernel":56,"gl":3}],33:[function(require,module,exports){ const { utils } = require('../utils'); @@ -9562,10 +9561,12 @@ class Kernel { setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; - this.argumentTypes = []; - for (let i = 0; i < args.length; i++) { - const argType = utils.getVariableType(args[i], this.strictIntegers); - this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + } } } @@ -11182,7 +11183,6 @@ const operatorMap = { module.exports = { WebGLFunctionNode }; - },{"../function-node":10}],37:[function(require,module,exports){ const { WebGLKernelValueBoolean } = require('./kernel-value/boolean'); const { WebGLKernelValueFloat } = require('./kernel-value/float'); @@ -12325,7 +12325,10 @@ class WebGLKernel extends GLKernel { setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; - this.argumentTypes = []; + const needsArgumentTypes = this.argumentTypes === null; + if (needsArgumentTypes) { + this.argumentTypes = []; + } this.argumentSizes = []; this.argumentBitRatios = []; if (!this.precision) { @@ -12342,8 +12345,13 @@ class WebGLKernel extends GLKernel { for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; - const type = utils.getVariableType(value, this.strictIntegers); - this.argumentTypes.push(type); + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); @@ -14767,6 +14775,10 @@ class GPU { source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, @@ -14823,7 +14835,7 @@ class GPU { return newKernel.renderOutput(); } } - }, upgradeDeprecatedCreateKernelSettings(settings) || {}); + }, settingsCopy); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); @@ -14856,7 +14868,12 @@ class GPU { } } - const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + const kernel = this.createKernel(fn, settingsCopy); + if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { @@ -14971,6 +14988,7 @@ module.exports = { kernelOrder, kernelTypes }; + },{"./backend/cpu/kernel":8,"./backend/headless-gl/kernel":32,"./backend/web-gl/kernel":56,"./backend/web-gl2/kernel":80,"./kernel-run-shortcut":86,"./utils":89,"gpu-mock.js":4}],84:[function(require,module,exports){ const { GPU } = require('./gpu'); const { alias } = require('./alias'); diff --git a/src/backend/kernel.js b/src/backend/kernel.js index bb91246d..457de3f3 100644 --- a/src/backend/kernel.js +++ b/src/backend/kernel.js @@ -258,10 +258,12 @@ class Kernel { setupArguments(args) { if (!this.argumentTypes) { this.kernelArguments = []; - this.argumentTypes = []; - for (let i = 0; i < args.length; i++) { - const argType = utils.getVariableType(args[i], this.strictIntegers); - this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + if (!this.argumentTypes) { + this.argumentTypes = []; + for (let i = 0; i < args.length; i++) { + const argType = utils.getVariableType(args[i], this.strictIntegers); + this.argumentTypes.push(argType === 'Integer' ? 'Number' : argType); + } } } diff --git a/src/backend/web-gl/kernel.js b/src/backend/web-gl/kernel.js index 9d867ee2..c9832b62 100644 --- a/src/backend/web-gl/kernel.js +++ b/src/backend/web-gl/kernel.js @@ -359,8 +359,11 @@ class WebGLKernel extends GLKernel { setupArguments(args) { this.kernelArguments = []; this.argumentTextureCount = 0; + const needsArgumentTypes = this.argumentTypes === null; // TODO: remove - this.argumentTypes = []; + if (needsArgumentTypes) { + this.argumentTypes = []; + } this.argumentSizes = []; this.argumentBitRatios = []; // TODO: end remove @@ -379,8 +382,13 @@ class WebGLKernel extends GLKernel { for (let index = 0; index < args.length; index++) { const value = args[index]; const name = this.argumentNames[index]; - const type = utils.getVariableType(value, this.strictIntegers); - this.argumentTypes.push(type); + let type; + if (needsArgumentTypes) { + type = utils.getVariableType(value, this.strictIntegers); + this.argumentTypes.push(type); + } else { + type = this.argumentTypes[index]; + } const KernelValue = this.constructor.lookupKernelValueType(type, this.dynamicArguments ? 'dynamic' : 'static', this.precision); if (KernelValue === null) { throw new Error('unsupported argument'); diff --git a/src/gpu.js b/src/gpu.js index 6bb6b3c7..55550958 100644 --- a/src/gpu.js +++ b/src/gpu.js @@ -210,6 +210,11 @@ class GPU { source = typeof source === 'function' ? source.toString() : source; const switchableKernels = {}; + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings) || {}; + // handle conversion of argumentTypes + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } const mergedSettings = Object.assign({ context: this.context, canvas: this.canvas, @@ -266,7 +271,7 @@ class GPU { return newKernel.renderOutput(); } } - }, upgradeDeprecatedCreateKernelSettings(settings) || {}); + }, settingsCopy); const kernel = kernelRunShortcut(new this.Kernel(source, mergedSettings)); @@ -331,7 +336,13 @@ class GPU { } } - const kernel = this.createKernel(fn, upgradeDeprecatedCreateKernelSettings(settings)); + const settingsCopy = upgradeDeprecatedCreateKernelSettings(settings); + // handle conversion of argumentTypes + if (settings && typeof settings.argumentTypes === 'object') { + settingsCopy.argumentTypes = Object.keys(settings.argumentTypes).map(argumentName => settings.argumentTypes[argumentName]); + } + const kernel = this.createKernel(fn, settingsCopy); + if (Array.isArray(arguments[0])) { const functions = arguments[0]; for (let i = 0; i < functions.length; i++) { diff --git a/test/all.html b/test/all.html index 894b06a4..63415b1f 100644 --- a/test/all.html +++ b/test/all.html @@ -163,6 +163,7 @@ + diff --git a/test/issues/470-modulus-wrong.js b/test/issues/470-modulus-wrong.js new file mode 100644 index 00000000..0f9c0e7f --- /dev/null +++ b/test/issues/470-modulus-wrong.js @@ -0,0 +1,53 @@ +const { assert, skip, test, module: describe } = require('qunit'); +const { GPU } = require('../../src'); + +describe('issue #470 - modulus wrong'); + +function testModulusWrong(mode) { + const gpu = new GPU({ mode }); + const kernel = gpu.createKernel(function(mod) { + return this.thread.x % mod; + }, { + output: [10], + argumentTypes: { + mod: 'Integer', + }, + }); + + const result = kernel(6); + assert.equal(kernel.argumentTypes[0], 'Integer'); + assert.equal(result[0], 0 % 6); + assert.equal(result[1], 1 % 6); + assert.equal(result[2], 2 % 6); + assert.equal(result[3], 3 % 6); + assert.equal(result[4], 4 % 6); + assert.equal(result[5], 5 % 6); + assert.equal(result[6], 6 % 6); + assert.equal(result[7], 7 % 6); + assert.equal(result[8], 8 % 6); + assert.equal(result[9], 9 % 6); +} + +test('auto', () => { + testModulusWrong(); +}); + +test('gpu', () => { + testModulusWrong('gpu'); +}); + +(GPU.isWebGLSupported ? test : skip)('webgl', () => { + testModulusWrong('webgl'); +}); + +(GPU.isWebGL2Supported ? test : skip)('webgl2', () => { + testModulusWrong('webgl2'); +}); + +(GPU.isHeadlessGLSupported ? test : skip)('headlessgl', () => { + testModulusWrong('headlessgl'); +}); + +test('cpu', () => { + testModulusWrong('cpu'); +});