make uniforms only set if their values indeed change, and add tests

This commit is contained in:
Robert Plummer 2018-03-06 10:42:24 -05:00
parent 2f37e8762d
commit 5850030e81
9 changed files with 386 additions and 98 deletions

View File

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.0.6
* @date Sat Mar 03 2018 14:24:37 GMT-0500 (EST)
* @date Tue Mar 06 2018 09:55:56 GMT-0500 (EST)
*
* @license MIT
* The MIT License

2
bin/gpu-core.min.js vendored
View File

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.0.6
* @date Sat Mar 03 2018 14:24:37 GMT-0500 (EST)
* @date Tue Mar 06 2018 09:55:56 GMT-0500 (EST)
*
* @license MIT
* The MIT License

View File

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.0.6
* @date Sat Mar 03 2018 14:24:37 GMT-0500 (EST)
* @date Tue Mar 06 2018 09:55:57 GMT-0500 (EST)
*
* @license MIT
* The MIT License
@ -2780,7 +2780,7 @@ function removeNoise(str) {
}
module.exports = function (gpuKernel, name) {
return '() => {\n ' + kernelRunShortcut.toString() + ';\n const utils = {\n allPropertiesOf: ' + removeNoise(utils.allPropertiesOf.toString()) + ',\n clone: ' + removeNoise(utils.clone.toString()) + ',\n splitArray: ' + removeNoise(utils.splitArray.toString()) + ',\n getArgumentType: ' + removeNoise(utils.getArgumentType.toString()) + ',\n getDimensions: ' + removeNoise(utils.getDimensions.toString()) + ',\n dimToTexSize: ' + removeNoise(utils.dimToTexSize.toString()) + ',\n flattenTo: ' + removeNoise(utils.flattenTo.toString()) + ',\n flatten2dArrayTo: ' + removeNoise(utils.flatten2dArrayTo.toString()) + ',\n flatten3dArrayTo: ' + removeNoise(utils.flatten3dArrayTo.toString()) + ',\n systemEndianness: \'' + removeNoise(utils.systemEndianness()) + '\',\n initWebGl: ' + removeNoise(utils.initWebGl.toString()) + ',\n isArray: ' + removeNoise(utils.isArray.toString()) + '\n };\n const Utils = utils;\n const canvases = [];\n const maxTexSizes = {};\n class ' + (name || 'Kernel') + ' {\n constructor() {\n this.maxTexSize = null;\n this.argumentsLength = 0;\n this._canvas = null;\n this._webGl = null;\n this.built = false;\n this.program = null;\n this.paramNames = ' + JSON.stringify(gpuKernel.paramNames) + ';\n this.paramTypes = ' + JSON.stringify(gpuKernel.paramTypes) + ';\n this.texSize = ' + JSON.stringify(gpuKernel.texSize) + ';\n this.output = ' + JSON.stringify(gpuKernel.output) + ';\n this.compiledFragShaderString = `' + gpuKernel.compiledFragShaderString + '`;\n\t\t this.compiledVertShaderString = `' + gpuKernel.compiledVertShaderString + '`;\n\t\t this.programUniformLocationCache = {};\n\t\t this.textureCache = {};\n\t\t this.subKernelOutputTextures = null;\n\t\t this.subKernelOutputVariableNames = null;\n }\n ' + removeFnNoise(gpuKernel._getFragShaderString.toString()) + '\n ' + removeFnNoise(gpuKernel._getVertShaderString.toString()) + '\n validateOptions() {}\n setupParams() {}\n setCanvas(canvas) { this._canvas = canvas; return this; }\n setWebGl(webGl) { this._webGl = webGl; return this; }\n ' + removeFnNoise(gpuKernel.getUniformLocation.toString()) + '\n ' + removeFnNoise(gpuKernel.setupParams.toString()) + '\n ' + removeFnNoise(gpuKernel.build.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.run.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._addArgument.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getArgumentTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.renderOutput.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.updateMaxTexSize.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._setupOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n };\n return kernelRunShortcut(new Kernel());\n };';
return '() => {\n ' + kernelRunShortcut.toString() + ';\n const utils = {\n allPropertiesOf: ' + removeNoise(utils.allPropertiesOf.toString()) + ',\n clone: ' + removeNoise(utils.clone.toString()) + ',\n splitArray: ' + removeNoise(utils.splitArray.toString()) + ',\n getArgumentType: ' + removeNoise(utils.getArgumentType.toString()) + ',\n getDimensions: ' + removeNoise(utils.getDimensions.toString()) + ',\n dimToTexSize: ' + removeNoise(utils.dimToTexSize.toString()) + ',\n flattenTo: ' + removeNoise(utils.flattenTo.toString()) + ',\n flatten2dArrayTo: ' + removeNoise(utils.flatten2dArrayTo.toString()) + ',\n flatten3dArrayTo: ' + removeNoise(utils.flatten3dArrayTo.toString()) + ',\n systemEndianness: \'' + removeNoise(utils.systemEndianness()) + '\',\n initWebGl: ' + removeNoise(utils.initWebGl.toString()) + ',\n isArray: ' + removeNoise(utils.isArray.toString()) + '\n };\n const Utils = utils;\n const canvases = [];\n const maxTexSizes = {};\n class ' + (name || 'Kernel') + ' {\n constructor() {\n this.maxTexSize = null;\n this.argumentsLength = 0;\n this._canvas = null;\n this._webGl = null;\n this.built = false;\n this.program = null;\n this.paramNames = ' + JSON.stringify(gpuKernel.paramNames) + ';\n this.paramTypes = ' + JSON.stringify(gpuKernel.paramTypes) + ';\n this.texSize = ' + JSON.stringify(gpuKernel.texSize) + ';\n this.output = ' + JSON.stringify(gpuKernel.output) + ';\n this.compiledFragShaderString = `' + gpuKernel.compiledFragShaderString + '`;\n\t\t this.compiledVertShaderString = `' + gpuKernel.compiledVertShaderString + '`;\n\t\t this.programUniformLocationCache = {};\n\t\t this.textureCache = {};\n\t\t this.subKernelOutputTextures = null;\n\t\t this.subKernelOutputVariableNames = null;\n\t\t this.uniform1fCache = {};\n\t\t this.uniform1iCache = {};\n\t\t this.uniform2fCache = {};\n\t\t this.uniform2fvCache = {};\n\t\t this.uniform3fvCache = {};\n }\n ' + removeFnNoise(gpuKernel._getFragShaderString.toString()) + '\n ' + removeFnNoise(gpuKernel._getVertShaderString.toString()) + '\n validateOptions() {}\n setupParams() {}\n setCanvas(canvas) { this._canvas = canvas; return this; }\n setWebGl(webGl) { this._webGl = webGl; return this; }\n ' + removeFnNoise(gpuKernel.getUniformLocation.toString()) + '\n ' + removeFnNoise(gpuKernel.setupParams.toString()) + '\n ' + removeFnNoise(gpuKernel.build.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.run.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._addArgument.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getArgumentTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.renderOutput.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.updateMaxTexSize.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._setupOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform1f.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform1i.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform2f.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform2fv.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform3fv.toString()) + ' \n };\n return kernelRunShortcut(new Kernel());\n };';
};
},{"../../core/utils":25,"../kernel-run-shortcut":9}],14:[function(require,module,exports){
'use strict';
@ -2828,6 +2828,11 @@ module.exports = function (_KernelBase) {
_this.extDrawBuffersMap = null;
_this.outputTexture = null;
_this.maxTexSize = null;
_this.uniform1fCache = {};
_this.uniform1iCache = {};
_this.uniform2fCache = {};
_this.uniform2fvCache = {};
_this.uniform3fvCache = {};
if (!_this._webGl) _this._webGl = utils.initWebGl(_this.getCanvas());
return _this;
}
@ -3010,14 +3015,11 @@ module.exports = function (_KernelBase) {
gl.scissor(0, 0, texSize[0], texSize[1]);
if (!this.hardcodeConstants) {
var uOutputDimLoc = this.getUniformLocation('uOutputDim');
gl.uniform3fv(uOutputDimLoc, this.threadDim);
var uTexSizeLoc = this.getUniformLocation('uTexSize');
gl.uniform2fv(uTexSizeLoc, texSize);
this.setUniform3fv('uOutputDim', this.threadDim);
this.setUniform2fv('uTexSize', texSize);
}
var ratioLoc = this.getUniformLocation('ratio');
gl.uniform2f(ratioLoc, texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.argumentsLength = 0;
for (var texIndex = 0; texIndex < paramNames.length; texIndex++) {
@ -3189,6 +3191,71 @@ module.exports = function (_KernelBase) {
value: function detachTextureCache(name) {
delete this.textureCache[name];
}
}, {
key: 'setUniform1f',
value: function setUniform1f(name, value) {
if (this.uniform1fCache.hasOwnProperty(name)) {
var cache = this.uniform1fCache[name];
if (value === cache) {
return;
}
}
this.uniform1fCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform1f(loc, value);
}
}, {
key: 'setUniform1i',
value: function setUniform1i(name, value) {
if (this.uniform1iCache.hasOwnProperty(name)) {
var cache = this.uniform1iCache[name];
if (value === cache) {
return;
}
}
this.uniform1iCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform1i(loc, value);
}
}, {
key: 'setUniform2f',
value: function setUniform2f(name, value1, value2) {
if (this.uniform2fCache.hasOwnProperty(name)) {
var cache = this.uniform2fCache[name];
if (value1 === cache[0] && value2 === cache[1]) {
return;
}
}
this.uniform2fCache[name] = [value1, value2];
var loc = this.getUniformLocation(name);
this._webGl.uniform2f(loc, value1, value2);
}
}, {
key: 'setUniform2fv',
value: function setUniform2fv(name, value) {
if (this.uniform2fvCache.hasOwnProperty(name)) {
var cache = this.uniform2fvCache[name];
if (value[0] === cache[0] && value[1] === cache[1]) {
return;
}
}
this.uniform2fvCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform2fv(loc, value);
}
}, {
key: 'setUniform3fv',
value: function setUniform3fv(name, value) {
if (this.uniform3fvCache.hasOwnProperty(name)) {
var cache = this.uniform3fvCache[name];
if (value[0] === cache[0] && value[1] === cache[1] && value[2] === cache[2]) {
return;
}
}
this.uniform3fvCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform3fv(loc, value);
}
}, {
@ -3261,21 +3328,16 @@ module.exports = function (_KernelBase) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size[0], size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
}
var loc = this.getUniformLocation('user_' + name);
var locSize = this.getUniformLocation('user_' + name + 'Size');
var dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(dimLoc, dim);
gl.uniform2fv(locSize, size);
this.setUniform3fv('user_' + name + 'Dim', dim);
this.setUniform2fv('user_' + name + 'Size', size);
}
gl.uniform1i(loc, this.argumentsLength);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
case 'Number':
{
var _loc = this.getUniformLocation('user_' + name);
gl.uniform1f(_loc, value);
this.setUniform1f('user_' + name, value);
break;
}
case 'Input':
@ -3310,15 +3372,11 @@ module.exports = function (_KernelBase) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _size[0], _size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, _buffer);
}
var _loc2 = this.getUniformLocation('user_' + name);
var _locSize = this.getUniformLocation('user_' + name + 'Size');
var _dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(_dimLoc, _dim);
gl.uniform2fv(_locSize, _size);
this.setUniform3fv('user_' + name + 'Dim', _dim);
this.setUniform2fv('user_' + name + 'Size', _size);
}
gl.uniform1i(_loc2, this.argumentsLength);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
case 'Texture':
@ -3330,13 +3388,9 @@ module.exports = function (_KernelBase) {
gl.activeTexture(gl.TEXTURE0 + this.argumentsLength);
gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
var _loc3 = this.getUniformLocation('user_' + name);
var _locSize2 = this.getUniformLocation('user_' + name + 'Size');
var _dimLoc2 = this.getUniformLocation('user_' + name + 'Dim');
gl.uniform3fv(_dimLoc2, _dim2);
gl.uniform2fv(_locSize2, _size2);
gl.uniform1i(_loc3, this.argumentsLength);
this.setUniform3fv('user_' + name + 'Dim', _dim2);
this.setUniform2fv('user_' + name + 'Size', _size2);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
default:

12
bin/gpu.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -15,5 +15,5 @@ function removeNoise(str) {
}
module.exports = function (gpuKernel, name) {
return '() => {\n ' + kernelRunShortcut.toString() + ';\n const utils = {\n allPropertiesOf: ' + removeNoise(utils.allPropertiesOf.toString()) + ',\n clone: ' + removeNoise(utils.clone.toString()) + ',\n splitArray: ' + removeNoise(utils.splitArray.toString()) + ',\n getArgumentType: ' + removeNoise(utils.getArgumentType.toString()) + ',\n getDimensions: ' + removeNoise(utils.getDimensions.toString()) + ',\n dimToTexSize: ' + removeNoise(utils.dimToTexSize.toString()) + ',\n flattenTo: ' + removeNoise(utils.flattenTo.toString()) + ',\n flatten2dArrayTo: ' + removeNoise(utils.flatten2dArrayTo.toString()) + ',\n flatten3dArrayTo: ' + removeNoise(utils.flatten3dArrayTo.toString()) + ',\n systemEndianness: \'' + removeNoise(utils.systemEndianness()) + '\',\n initWebGl: ' + removeNoise(utils.initWebGl.toString()) + ',\n isArray: ' + removeNoise(utils.isArray.toString()) + '\n };\n const Utils = utils;\n const canvases = [];\n const maxTexSizes = {};\n class ' + (name || 'Kernel') + ' {\n constructor() {\n this.maxTexSize = null;\n this.argumentsLength = 0;\n this._canvas = null;\n this._webGl = null;\n this.built = false;\n this.program = null;\n this.paramNames = ' + JSON.stringify(gpuKernel.paramNames) + ';\n this.paramTypes = ' + JSON.stringify(gpuKernel.paramTypes) + ';\n this.texSize = ' + JSON.stringify(gpuKernel.texSize) + ';\n this.output = ' + JSON.stringify(gpuKernel.output) + ';\n this.compiledFragShaderString = `' + gpuKernel.compiledFragShaderString + '`;\n\t\t this.compiledVertShaderString = `' + gpuKernel.compiledVertShaderString + '`;\n\t\t this.programUniformLocationCache = {};\n\t\t this.textureCache = {};\n\t\t this.subKernelOutputTextures = null;\n\t\t this.subKernelOutputVariableNames = null;\n }\n ' + removeFnNoise(gpuKernel._getFragShaderString.toString()) + '\n ' + removeFnNoise(gpuKernel._getVertShaderString.toString()) + '\n validateOptions() {}\n setupParams() {}\n setCanvas(canvas) { this._canvas = canvas; return this; }\n setWebGl(webGl) { this._webGl = webGl; return this; }\n ' + removeFnNoise(gpuKernel.getUniformLocation.toString()) + '\n ' + removeFnNoise(gpuKernel.setupParams.toString()) + '\n ' + removeFnNoise(gpuKernel.build.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.run.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._addArgument.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getArgumentTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.renderOutput.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.updateMaxTexSize.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._setupOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n };\n return kernelRunShortcut(new Kernel());\n };';
return '() => {\n ' + kernelRunShortcut.toString() + ';\n const utils = {\n allPropertiesOf: ' + removeNoise(utils.allPropertiesOf.toString()) + ',\n clone: ' + removeNoise(utils.clone.toString()) + ',\n splitArray: ' + removeNoise(utils.splitArray.toString()) + ',\n getArgumentType: ' + removeNoise(utils.getArgumentType.toString()) + ',\n getDimensions: ' + removeNoise(utils.getDimensions.toString()) + ',\n dimToTexSize: ' + removeNoise(utils.dimToTexSize.toString()) + ',\n flattenTo: ' + removeNoise(utils.flattenTo.toString()) + ',\n flatten2dArrayTo: ' + removeNoise(utils.flatten2dArrayTo.toString()) + ',\n flatten3dArrayTo: ' + removeNoise(utils.flatten3dArrayTo.toString()) + ',\n systemEndianness: \'' + removeNoise(utils.systemEndianness()) + '\',\n initWebGl: ' + removeNoise(utils.initWebGl.toString()) + ',\n isArray: ' + removeNoise(utils.isArray.toString()) + '\n };\n const Utils = utils;\n const canvases = [];\n const maxTexSizes = {};\n class ' + (name || 'Kernel') + ' {\n constructor() {\n this.maxTexSize = null;\n this.argumentsLength = 0;\n this._canvas = null;\n this._webGl = null;\n this.built = false;\n this.program = null;\n this.paramNames = ' + JSON.stringify(gpuKernel.paramNames) + ';\n this.paramTypes = ' + JSON.stringify(gpuKernel.paramTypes) + ';\n this.texSize = ' + JSON.stringify(gpuKernel.texSize) + ';\n this.output = ' + JSON.stringify(gpuKernel.output) + ';\n this.compiledFragShaderString = `' + gpuKernel.compiledFragShaderString + '`;\n\t\t this.compiledVertShaderString = `' + gpuKernel.compiledVertShaderString + '`;\n\t\t this.programUniformLocationCache = {};\n\t\t this.textureCache = {};\n\t\t this.subKernelOutputTextures = null;\n\t\t this.subKernelOutputVariableNames = null;\n\t\t this.uniform1fCache = {};\n\t\t this.uniform1iCache = {};\n\t\t this.uniform2fCache = {};\n\t\t this.uniform2fvCache = {};\n\t\t this.uniform3fvCache = {};\n }\n ' + removeFnNoise(gpuKernel._getFragShaderString.toString()) + '\n ' + removeFnNoise(gpuKernel._getVertShaderString.toString()) + '\n validateOptions() {}\n setupParams() {}\n setCanvas(canvas) { this._canvas = canvas; return this; }\n setWebGl(webGl) { this._webGl = webGl; return this; }\n ' + removeFnNoise(gpuKernel.getUniformLocation.toString()) + '\n ' + removeFnNoise(gpuKernel.setupParams.toString()) + '\n ' + removeFnNoise(gpuKernel.build.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.run.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._addArgument.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getArgumentTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.getOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.renderOutput.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.updateMaxTexSize.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel._setupOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform1f.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform1i.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform2f.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform2fv.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.setUniform3fv.toString()) + ' \n };\n return kernelRunShortcut(new Kernel());\n };';
};

View File

@ -66,6 +66,11 @@ module.exports = function (_KernelBase) {
_this.extDrawBuffersMap = null;
_this.outputTexture = null;
_this.maxTexSize = null;
_this.uniform1fCache = {};
_this.uniform1iCache = {};
_this.uniform2fCache = {};
_this.uniform2fvCache = {};
_this.uniform3fvCache = {};
if (!_this._webGl) _this._webGl = utils.initWebGl(_this.getCanvas());
return _this;
}
@ -280,14 +285,11 @@ module.exports = function (_KernelBase) {
gl.scissor(0, 0, texSize[0], texSize[1]);
if (!this.hardcodeConstants) {
var uOutputDimLoc = this.getUniformLocation('uOutputDim');
gl.uniform3fv(uOutputDimLoc, this.threadDim);
var uTexSizeLoc = this.getUniformLocation('uTexSize');
gl.uniform2fv(uTexSizeLoc, texSize);
this.setUniform3fv('uOutputDim', this.threadDim);
this.setUniform2fv('uTexSize', texSize);
}
var ratioLoc = this.getUniformLocation('ratio');
gl.uniform2f(ratioLoc, texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.argumentsLength = 0;
for (var texIndex = 0; texIndex < paramNames.length; texIndex++) {
@ -533,6 +535,71 @@ module.exports = function (_KernelBase) {
value: function detachTextureCache(name) {
delete this.textureCache[name];
}
}, {
key: 'setUniform1f',
value: function setUniform1f(name, value) {
if (this.uniform1fCache.hasOwnProperty(name)) {
var cache = this.uniform1fCache[name];
if (value === cache) {
return;
}
}
this.uniform1fCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform1f(loc, value);
}
}, {
key: 'setUniform1i',
value: function setUniform1i(name, value) {
if (this.uniform1iCache.hasOwnProperty(name)) {
var cache = this.uniform1iCache[name];
if (value === cache) {
return;
}
}
this.uniform1iCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform1i(loc, value);
}
}, {
key: 'setUniform2f',
value: function setUniform2f(name, value1, value2) {
if (this.uniform2fCache.hasOwnProperty(name)) {
var cache = this.uniform2fCache[name];
if (value1 === cache[0] && value2 === cache[1]) {
return;
}
}
this.uniform2fCache[name] = [value1, value2];
var loc = this.getUniformLocation(name);
this._webGl.uniform2f(loc, value1, value2);
}
}, {
key: 'setUniform2fv',
value: function setUniform2fv(name, value) {
if (this.uniform2fvCache.hasOwnProperty(name)) {
var cache = this.uniform2fvCache[name];
if (value[0] === cache[0] && value[1] === cache[1]) {
return;
}
}
this.uniform2fvCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform2fv(loc, value);
}
}, {
key: 'setUniform3fv',
value: function setUniform3fv(name, value) {
if (this.uniform3fvCache.hasOwnProperty(name)) {
var cache = this.uniform3fvCache[name];
if (value[0] === cache[0] && value[1] === cache[1] && value[2] === cache[2]) {
return;
}
}
this.uniform3fvCache[name] = value;
var loc = this.getUniformLocation(name);
this._webGl.uniform3fv(loc, value);
}
/**
* @memberOf WebGLKernel#
@ -641,21 +708,16 @@ module.exports = function (_KernelBase) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size[0], size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
}
var loc = this.getUniformLocation('user_' + name);
var locSize = this.getUniformLocation('user_' + name + 'Size');
var dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(dimLoc, dim);
gl.uniform2fv(locSize, size);
this.setUniform3fv('user_' + name + 'Dim', dim);
this.setUniform2fv('user_' + name + 'Size', size);
}
gl.uniform1i(loc, this.argumentsLength);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
case 'Number':
{
var _loc = this.getUniformLocation('user_' + name);
gl.uniform1f(_loc, value);
this.setUniform1f('user_' + name, value);
break;
}
case 'Input':
@ -690,15 +752,11 @@ module.exports = function (_KernelBase) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, _size[0], _size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, _buffer);
}
var _loc2 = this.getUniformLocation('user_' + name);
var _locSize = this.getUniformLocation('user_' + name + 'Size');
var _dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(_dimLoc, _dim);
gl.uniform2fv(_locSize, _size);
this.setUniform3fv('user_' + name + 'Dim', _dim);
this.setUniform2fv('user_' + name + 'Size', _size);
}
gl.uniform1i(_loc2, this.argumentsLength);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
case 'Texture':
@ -710,13 +768,9 @@ module.exports = function (_KernelBase) {
gl.activeTexture(gl.TEXTURE0 + this.argumentsLength);
gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
var _loc3 = this.getUniformLocation('user_' + name);
var _locSize2 = this.getUniformLocation('user_' + name + 'Size');
var _dimLoc2 = this.getUniformLocation('user_' + name + 'Dim');
gl.uniform3fv(_dimLoc2, _dim2);
gl.uniform2fv(_locSize2, _size2);
gl.uniform1i(_loc3, this.argumentsLength);
this.setUniform3fv('user_' + name + 'Dim', _dim2);
this.setUniform2fv('user_' + name + 'Size', _size2);
this.setUniform1i('user_' + name, this.argumentsLength);
break;
}
default:

View File

@ -52,6 +52,11 @@ module.exports = function(gpuKernel, name) {
this.textureCache = {};
this.subKernelOutputTextures = null;
this.subKernelOutputVariableNames = null;
this.uniform1fCache = {};
this.uniform1iCache = {};
this.uniform2fCache = {};
this.uniform2fvCache = {};
this.uniform3fvCache = {};
}
${ removeFnNoise(gpuKernel._getFragShaderString.toString()) }
${ removeFnNoise(gpuKernel._getVertShaderString.toString()) }
@ -71,6 +76,11 @@ module.exports = function(gpuKernel, name) {
${ removeFnNoise(gpuKernel.updateMaxTexSize.toString()) }
${ removeFnNoise(gpuKernel._setupOutputTexture.toString()) }
${ removeFnNoise(gpuKernel.detachTextureCache.toString()) }
${ removeFnNoise(gpuKernel.setUniform1f.toString()) }
${ removeFnNoise(gpuKernel.setUniform1i.toString()) }
${ removeFnNoise(gpuKernel.setUniform2f.toString()) }
${ removeFnNoise(gpuKernel.setUniform2fv.toString()) }
${ removeFnNoise(gpuKernel.setUniform3fv.toString()) }
};
return kernelRunShortcut(new Kernel());
};`;

View File

@ -53,6 +53,11 @@ module.exports = class WebGLKernel extends KernelBase {
this.extDrawBuffersMap = null;
this.outputTexture = null;
this.maxTexSize = null;
this.uniform1fCache = {};
this.uniform1iCache = {};
this.uniform2fCache = {};
this.uniform2fvCache = {};
this.uniform3fvCache = {};
if (!this._webGl) this._webGl = utils.initWebGl(this.getCanvas());
}
@ -268,14 +273,11 @@ module.exports = class WebGLKernel extends KernelBase {
gl.scissor(0, 0, texSize[0], texSize[1]);
if (!this.hardcodeConstants) {
const uOutputDimLoc = this.getUniformLocation('uOutputDim');
gl.uniform3fv(uOutputDimLoc, this.threadDim);
const uTexSizeLoc = this.getUniformLocation('uTexSize');
gl.uniform2fv(uTexSizeLoc, texSize);
this.setUniform3fv('uOutputDim', this.threadDim);
this.setUniform2fv('uTexSize', texSize);
}
const ratioLoc = this.getUniformLocation('ratio');
gl.uniform2f(ratioLoc, texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.setUniform2f('ratio', texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
this.argumentsLength = 0;
for (let texIndex = 0; texIndex < paramNames.length; texIndex++) {
@ -501,6 +503,76 @@ module.exports = class WebGLKernel extends KernelBase {
delete this.textureCache[name];
}
setUniform1f(name, value) {
if (this.uniform1fCache.hasOwnProperty(name)) {
const cache = this.uniform1fCache[name];
if (value === cache) {
return;
}
}
this.uniform1fCache[name] = value;
const loc = this.getUniformLocation(name);
this._webGl.uniform1f(loc, value);
}
setUniform1i(name, value) {
if (this.uniform1iCache.hasOwnProperty(name)) {
const cache = this.uniform1iCache[name];
if (value === cache) {
return;
}
}
this.uniform1iCache[name] = value;
const loc = this.getUniformLocation(name);
this._webGl.uniform1i(loc, value);
}
setUniform2f(name, value1, value2) {
if (this.uniform2fCache.hasOwnProperty(name)) {
const cache = this.uniform2fCache[name];
if (
value1 === cache[0] &&
value2 === cache[1]
) {
return;
}
}
this.uniform2fCache[name] = [value1, value2];
const loc = this.getUniformLocation(name);
this._webGl.uniform2f(loc, value1, value2);
}
setUniform2fv(name, value) {
if (this.uniform2fvCache.hasOwnProperty(name)) {
const cache = this.uniform2fvCache[name];
if (
value[0] === cache[0] &&
value[1] === cache[1]
) {
return;
}
}
this.uniform2fvCache[name] = value;
const loc = this.getUniformLocation(name);
this._webGl.uniform2fv(loc, value);
}
setUniform3fv(name, value) {
if (this.uniform3fvCache.hasOwnProperty(name)) {
const cache = this.uniform3fvCache[name];
if (
value[0] === cache[0] &&
value[1] === cache[1] &&
value[2] === cache[2]
) {
return;
}
}
this.uniform3fvCache[name] = value;
const loc = this.getUniformLocation(name);
this._webGl.uniform3fv(loc, value);
}
/**
* @memberOf WebGLKernel#
* @function
@ -599,21 +671,16 @@ module.exports = class WebGLKernel extends KernelBase {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size[0], size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
}
const loc = this.getUniformLocation('user_' + name);
const locSize = this.getUniformLocation('user_' + name + 'Size');
const dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(dimLoc, dim);
gl.uniform2fv(locSize, size);
this.setUniform3fv(`user_${name}Dim`, dim);
this.setUniform2fv(`user_${name}Size`, size);
}
gl.uniform1i(loc, this.argumentsLength);
this.setUniform1i(`user_${name}`, this.argumentsLength);
break;
}
case 'Number':
{
const loc = this.getUniformLocation('user_' + name);
gl.uniform1f(loc, value);
this.setUniform1f(`user_${name}`, value);
break;
}
case 'Input':
@ -648,15 +715,11 @@ module.exports = class WebGLKernel extends KernelBase {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size[0], size[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
}
const loc = this.getUniformLocation('user_' + name);
const locSize = this.getUniformLocation('user_' + name + 'Size');
const dimLoc = this.getUniformLocation('user_' + name + 'Dim');
if (!this.hardcodeConstants) {
gl.uniform3fv(dimLoc, dim);
gl.uniform2fv(locSize, size);
this.setUniform3fv(`user_${name}Dim`, dim);
this.setUniform2fv(`user_${name}Size`, size);
}
gl.uniform1i(loc, this.argumentsLength);
this.setUniform1i(`user_${name}`, this.argumentsLength);
break;
}
case 'Texture':
@ -668,13 +731,9 @@ module.exports = class WebGLKernel extends KernelBase {
gl.activeTexture(gl.TEXTURE0 + this.argumentsLength);
gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
const loc = this.getUniformLocation('user_' + name);
const locSize = this.getUniformLocation('user_' + name + 'Size');
const dimLoc = this.getUniformLocation('user_' + name + 'Dim');
gl.uniform3fv(dimLoc, dim);
gl.uniform2fv(locSize, size);
gl.uniform1i(loc, this.argumentsLength);
this.setUniform3fv(`user_${name}Dim`, dim);
this.setUniform2fv(`user_${name}Size`, size);
this.setUniform1i(`user_${name}`, this.argumentsLength);
break;
}
default:

View File

@ -28,4 +28,115 @@ QUnit.test('KernelBase paramTypes WebGL', function(assert) {
} catch (e) {}
assert.equal(kernel.paramTypes.length, 1);
assert.equal(kernel.paramTypes[0], 'Array');
});
QUnit.test('WebGLKernel.setUniform1f only calls webgl when values change', () => {
const kernel = new GPU.WebGLKernel('', { output: [1] });
let throws = false;
kernel._webGl = {
uniform1f: () => {
if (throws) new Error('This should not get called');
},
getUniformLocation: (name) => {
return name;
}
};
kernel.setUniform1f('test', 1);
QUnit.assert.equal(kernel.uniform1fCache['test'], 1);
throws = true;
kernel.setUniform1f('test', 1);
QUnit.assert.equal(kernel.uniform1fCache['test'], 1);
throws = false;
kernel.setUniform1f('test', 2);
QUnit.assert.equal(kernel.uniform1fCache['test'], 2);
});
QUnit.test('WebGLKernel.setUniform1i only calls webgl when values change', () => {
const kernel = new GPU.WebGLKernel('', { output: [1] });
let throws = false;
kernel._webGl = {
uniform1i: () => {
if (throws) new Error('This should not get called');
},
getUniformLocation: (name) => {
return name;
}
};
kernel.setUniform1i('test', 1);
QUnit.assert.equal(kernel.uniform1iCache['test'], 1);
throws = true;
kernel.setUniform1i('test', 1);
QUnit.assert.equal(kernel.uniform1iCache['test'], 1);
throws = false;
kernel.setUniform1i('test', 2);
QUnit.assert.equal(kernel.uniform1iCache['test'], 2);
});
QUnit.test('WebGLKernel.setUniform2f only calls webgl when values change', () => {
const kernel = new GPU.WebGLKernel('', { output: [1] });
let throws = false;
kernel._webGl = {
uniform2f: () => {
if (throws) new Error('This should not get called');
},
getUniformLocation: (name) => {
return name;
}
};
kernel.setUniform2f('test', 1, 2);
QUnit.assert.deepEqual(kernel.uniform2fCache['test'], [1, 2]);
throws = true;
kernel.setUniform2f('test', 1, 2);
QUnit.assert.deepEqual(kernel.uniform2fCache['test'], [1, 2]);
throws = false;
kernel.setUniform2f('test', 3, 4);
QUnit.assert.deepEqual(kernel.uniform2fCache['test'], [3, 4]);
});
QUnit.test('WebGLKernel.setUniform2fv only calls webgl when values change', () => {
const kernel = new GPU.WebGLKernel('', { output: [1] });
let throws = false;
kernel._webGl = {
uniform2fv: () => {
if (throws) new Error('This should not get called');
},
getUniformLocation: (name) => {
return name;
}
};
kernel.setUniform2fv('test', [1, 2]);
QUnit.assert.deepEqual(kernel.uniform2fvCache['test'], [1, 2]);
throws = true;
kernel.setUniform2fv('test', [1, 2]);
QUnit.assert.deepEqual(kernel.uniform2fvCache['test'], [1, 2]);
throws = false;
kernel.setUniform2fv('test', [2, 3]);
QUnit.assert.deepEqual(kernel.uniform2fvCache['test'], [2, 3]);
});
QUnit.test('WebGLKernel.setUniform3fv only calls webgl when values change', () => {
const kernel = new GPU.WebGLKernel('', { output: [1] });
let throws = false;
kernel._webGl = {
uniform3fv: () => {
if (throws) new Error('This should not get called');
},
getUniformLocation: (name) => {
return name;
}
};
kernel.setUniform3fv('test', [1, 2, 3]);
QUnit.assert.deepEqual(kernel.uniform3fvCache['test'], [1, 2, 3]);
throws = true;
kernel.setUniform3fv('test', [1, 2, 3]);
QUnit.assert.deepEqual(kernel.uniform3fvCache['test'], [1, 2, 3]);
throws = false;
kernel.setUniform3fv('test', [2, 3, 4]);
QUnit.assert.deepEqual(kernel.uniform3fvCache['test'], [2, 3, 4]);
});