Skip to content

Commit 502e97c

Browse files
Merge pull request #269 from gpujs/267-immutable-sub-kernels
fix #267 by refining implementation a bit
2 parents 26479a1 + 4eda877 commit 502e97c

File tree

13 files changed

+292
-219
lines changed

13 files changed

+292
-219
lines changed

bin/gpu-core.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* GPU Accelerated JavaScript
66
*
77
* @version 1.0.1
8-
* @date Tue Feb 27 2018 13:04:39 GMT-0500 (EST)
8+
* @date Wed Feb 28 2018 15:01:50 GMT-0500 (EST)
99
*
1010
* @license MIT
1111
* The MIT License

bin/gpu-core.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/gpu.js

Lines changed: 68 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* GPU Accelerated JavaScript
66
*
77
* @version 1.0.1
8-
* @date Tue Feb 27 2018 13:04:40 GMT-0500 (EST)
8+
* @date Wed Feb 28 2018 15:01:51 GMT-0500 (EST)
99
*
1010
* @license MIT
1111
* The MIT License
@@ -2787,7 +2787,7 @@ function removeNoise(str) {
27872787
}
27882788

27892789
module.exports = function (gpuKernel, name) {
2790-
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 }\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.detachOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n };\n return kernelRunShortcut(new Kernel());\n };';
2790+
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.detachOutputTexture.toString()) + '\n\t\t ' + removeFnNoise(gpuKernel.detachTextureCache.toString()) + '\n };\n return kernelRunShortcut(new Kernel());\n };';
27912791
};
27922792
},{"../../core/utils":25,"../kernel-run-shortcut":9}],14:[function(require,module,exports){
27932793
'use strict';
@@ -2992,25 +2992,12 @@ module.exports = function (_KernelBase) {
29922992
gl.enableVertexAttribArray(aTexCoordLoc);
29932993
gl.vertexAttribPointer(aTexCoordLoc, 2, gl.FLOAT, gl.FALSE, 0, texCoordOffset);
29942994

2995-
this.setupOutputTexture();
2995+
if (!this.outputImmutable) {
2996+
this.setupOutputTexture();
2997+
}
29962998

2997-
if (this.subKernelOutputTextures !== null) {
2998-
var extDrawBuffersMap = this.extDrawBuffersMap = [gl.COLOR_ATTACHMENT0];
2999-
for (var i = 0; i < this.subKernelOutputTextures.length; i++) {
3000-
var subKernelOutputTexture = this.subKernelOutputTextures[i];
3001-
extDrawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1);
3002-
gl.activeTexture(gl.TEXTURE0 + arguments.length + i);
3003-
gl.bindTexture(gl.TEXTURE_2D, subKernelOutputTexture);
3004-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3005-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3006-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
3007-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
3008-
if (this.floatOutput) {
3009-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null);
3010-
} else {
3011-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
3012-
}
3013-
}
2999+
if (this.subKernelOutputVariableNames !== null && this.subKernelOutputVariableNames.length > 0 && !this.outputImmutable) {
3000+
this.setupSubOutputTextures(this.subKernelOutputVariableNames.length);
30143001
}
30153002
}
30163003

@@ -3039,12 +3026,11 @@ module.exports = function (_KernelBase) {
30393026
var ratioLoc = this.getUniformLocation('ratio');
30403027
gl.uniform2f(ratioLoc, texSize[0] / this.maxTexSize[0], texSize[1] / this.maxTexSize[1]);
30413028

3042-
this.argumentsLength = 0;
3043-
for (var texIndex = 0; texIndex < paramNames.length; texIndex++) {
3044-
this._addArgument(arguments[texIndex], paramTypes[texIndex], paramNames[texIndex]);
3045-
}
3046-
30473029
if (this.graphical) {
3030+
this.argumentsLength = 0;
3031+
for (var texIndex = 0; texIndex < paramNames.length; texIndex++) {
3032+
this._addArgument(arguments[texIndex], paramTypes[texIndex], paramNames[texIndex]);
3033+
}
30483034
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
30493035
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
30503036
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
@@ -3058,14 +3044,23 @@ module.exports = function (_KernelBase) {
30583044
var outputTexture = this.outputTexture;
30593045
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0);
30603046

3061-
if (this.subKernelOutputTextures !== null) {
3047+
if (this.subKernelOutputVariableNames !== null) {
3048+
if (this.outputImmutable) {
3049+
this.subKernelOutputTextures = [];
3050+
this.setupSubOutputTextures(this.subKernelOutputVariableNames.length);
3051+
}
30623052
for (var i = 0; i < this.subKernelOutputTextures.length; i++) {
30633053
var subKernelOutputTexture = this.subKernelOutputTextures[i];
30643054
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i + 1, gl.TEXTURE_2D, subKernelOutputTexture, 0);
30653055
}
30663056
this.ext.drawBuffersWEBGL(this.extDrawBuffersMap);
30673057
}
30683058

3059+
this.argumentsLength = 0;
3060+
for (var _texIndex = 0; _texIndex < paramNames.length; _texIndex++) {
3061+
this._addArgument(arguments[_texIndex], paramTypes[_texIndex], paramNames[_texIndex]);
3062+
}
3063+
30693064
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
30703065

30713066
if (this.subKernelOutputTextures !== null) {
@@ -3133,14 +3128,14 @@ module.exports = function (_KernelBase) {
31333128
}, {
31343129
key: 'getOutputTexture',
31353130
value: function getOutputTexture() {
3136-
return this.getTextureCache('OUTPUT');
3131+
return this.outputTexture;
31373132
}
31383133

31393134

31403135
}, {
31413136
key: 'detachOutputTexture',
31423137
value: function detachOutputTexture() {
3143-
this.detachTextureCache('OUTPUT');
3138+
delete this.outputTexture;
31443139
}
31453140

31463141

@@ -3150,7 +3145,7 @@ module.exports = function (_KernelBase) {
31503145
var gl = this._webGl;
31513146
var texSize = this.texSize;
31523147
this.detachOutputTexture();
3153-
this.outputTexture = this.getOutputTexture();
3148+
this.outputTexture = this._webGl.createTexture();
31543149
gl.activeTexture(gl.TEXTURE0 + this.paramNames.length);
31553150
gl.bindTexture(gl.TEXTURE_2D, this.outputTexture);
31563151
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
@@ -3163,6 +3158,30 @@ module.exports = function (_KernelBase) {
31633158
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
31643159
}
31653160
}
3161+
}, {
3162+
key: 'setupSubOutputTextures',
3163+
value: function setupSubOutputTextures(length) {
3164+
var gl = this._webGl;
3165+
var texSize = this.texSize;
3166+
var extDrawBuffersMap = this.extDrawBuffersMap = [gl.COLOR_ATTACHMENT0];
3167+
var textures = this.subKernelOutputTextures = [];
3168+
for (var i = 0; i < length; i++) {
3169+
var texture = this._webGl.createTexture();
3170+
textures.push(texture);
3171+
extDrawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1);
3172+
gl.activeTexture(gl.TEXTURE0 + arguments.length + i);
3173+
gl.bindTexture(gl.TEXTURE_2D, texture);
3174+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
3175+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
3176+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
3177+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
3178+
if (this.floatOutput) {
3179+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null);
3180+
} else {
3181+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
3182+
}
3183+
}
3184+
}
31663185

31673186

31683187
}, {
@@ -3338,10 +3357,6 @@ module.exports = function (_KernelBase) {
33383357

33393358
var _size2 = inputTexture.size;
33403359

3341-
if (!this.outputImmutable && inputTexture.texture === this.outputTexture) {
3342-
this.setupOutputTexture();
3343-
}
3344-
33453360
gl.activeTexture(gl.TEXTURE0 + this.argumentsLength);
33463361
gl.bindTexture(gl.TEXTURE_2D, inputTexture.texture);
33473362

@@ -3598,6 +3613,8 @@ module.exports = function (_KernelBase) {
35983613
}, {
35993614
key: '_addKernels',
36003615
value: function _addKernels() {
3616+
var _this2 = this;
3617+
36013618
var builder = this.functionBuilder;
36023619
var gl = this._webGl;
36033620

@@ -3618,42 +3635,31 @@ module.exports = function (_KernelBase) {
36183635
if (this.subKernels !== null) {
36193636
var ext = this.ext = gl.getExtension('WEBGL_draw_buffers');
36203637
if (!ext) throw new Error('could not instantiate draw buffers extension');
3621-
this.subKernelOutputTextures = [];
36223638
this.subKernelOutputVariableNames = [];
3623-
for (var i = 0; i < this.subKernels.length; i++) {
3624-
var subKernel = this.subKernels[i];
3625-
builder.addSubKernel(subKernel, {
3626-
prototypeOnly: false,
3627-
constants: this.constants,
3628-
output: this.output,
3629-
debug: this.debug,
3630-
loopMaxIterations: this.loopMaxIterations
3631-
});
3632-
this.subKernelOutputTextures.push(this.getSubKernelTexture(i));
3633-
this.subKernelOutputVariableNames.push(subKernel.name + 'Result');
3634-
}
3639+
this.subKernels.forEach(function (subKernel) {
3640+
return _this2._addSubKernel(subKernel);
3641+
});
36353642
} else if (this.subKernelProperties !== null) {
36363643
var _ext = this.ext = gl.getExtension('WEBGL_draw_buffers');
36373644
if (!_ext) throw new Error('could not instantiate draw buffers extension');
3638-
this.subKernelOutputTextures = [];
36393645
this.subKernelOutputVariableNames = [];
3640-
var _i4 = 0;
3641-
for (var p in this.subKernelProperties) {
3642-
if (!this.subKernelProperties.hasOwnProperty(p)) continue;
3643-
var _subKernel = this.subKernelProperties[p];
3644-
builder.addSubKernel(_subKernel, {
3645-
prototypeOnly: false,
3646-
constants: this.constants,
3647-
output: this.output,
3648-
debug: this.debug,
3649-
loopMaxIterations: this.loopMaxIterations
3650-
});
3651-
this.subKernelOutputTextures.push(this.getSubKernelTexture(p));
3652-
this.subKernelOutputVariableNames.push(_subKernel.name + 'Result');
3653-
_i4++;
3654-
}
3646+
Object.keys(this.subKernelProperties).forEach(function (property) {
3647+
return _this2._addSubKernel(_this2.subKernelProperties[property]);
3648+
});
36553649
}
36563650
}
3651+
}, {
3652+
key: '_addSubKernel',
3653+
value: function _addSubKernel(subKernel) {
3654+
this.functionBuilder.addSubKernel(subKernel, {
3655+
prototypeOnly: false,
3656+
constants: this.constants,
3657+
output: this.output,
3658+
debug: this.debug,
3659+
loopMaxIterations: this.loopMaxIterations
3660+
});
3661+
this.subKernelOutputVariableNames.push(subKernel.name + 'Result');
3662+
}
36573663

36583664

36593665
}, {

bin/gpu.min.js

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)