fix leaking WegGl contexts

This commit is contained in:
Nick Hingston 2018-07-30 20:30:31 +01:00
parent 03077cedd1
commit 92612c1c2f
16 changed files with 453 additions and 47 deletions

View File

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.5.4
* @date Thu Jul 26 2018 17:35:34 GMT+0100 (BST)
* @date Mon Jul 30 2018 19:23:17 GMT+0100 (BST)
*
* @license MIT
* The MIT License

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

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.5.4
* @date Thu Jul 26 2018 17:35:34 GMT+0100 (BST)
* @date Mon Jul 30 2018 19:23:17 GMT+0100 (BST)
*
* @license MIT
* The MIT License

View File

@ -5,7 +5,7 @@
* GPU Accelerated JavaScript
*
* @version 1.5.4
* @date Thu Jul 26 2018 17:35:35 GMT+0100 (BST)
* @date Mon Jul 30 2018 19:23:18 GMT+0100 (BST)
*
* @license MIT
* The MIT License
@ -2146,6 +2146,18 @@ module.exports = function () {
value: function addNativeFunction(name, source) {
this.functionBuilder.addNativeFunction(name, source);
}
}, {
key: 'destroy',
value: function destroy() {
if (this.subKernels) {
for (var i = 0; i < this.subKernels.length; i++) {
this.subKernels[i].destroy();
}
}
console.log('destroy kernel');
}
}]);
return KernelBase;
@ -3249,6 +3261,8 @@ module.exports = function (gpuKernel, name) {
},{"../../core/utils":32,"../kernel-run-shortcut":9}],14:[function(require,module,exports){
'use strict';
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -3263,6 +3277,7 @@ var Texture = require('../../core/texture');
var fragShaderString = require('./shader-frag');
var vertShaderString = require('./shader-vert');
var kernelString = require('./kernel-string');
var canvases = [];
var maxTexSizes = {};
@ -3301,6 +3316,8 @@ module.exports = function (_KernelBase) {
_this.argumentsLength = 0;
_this.compiledFragShaderString = null;
_this.compiledVertShaderString = null;
_this.fragShader = null;
_this.vertShader = null;
_this.drawBuffersMap = null;
_this.outputTexture = null;
_this.maxTexSize = null;
@ -3405,6 +3422,17 @@ module.exports = function (_KernelBase) {
}, {
key: 'build',
value: function build() {
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
this.validateOptions();
this.setupParams(arguments);
this.updateMaxTexSize();
@ -3426,11 +3454,14 @@ module.exports = function (_KernelBase) {
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, compiledVertShaderString);
gl.compileShader(vertShader);
if (this.vertShader) {}
this.vertShader = vertShader;
var compiledFragShaderString = this._getFragShaderString(arguments);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, compiledFragShaderString);
gl.compileShader(fragShader);
this.fragShader = fragShader;
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
console.log(compiledVertShaderString);
@ -4309,6 +4340,53 @@ module.exports = function (_KernelBase) {
value: function addFunction(fn) {
this.functionBuilder.addFunction(null, fn);
}
}, {
key: 'destroy',
value: function destroy(removeCanvasReferences) {
_get(WebGLKernel.prototype.__proto__ || Object.getPrototypeOf(WebGLKernel.prototype), 'destroy', this).call(this);
if (this.outputTexture) {
this._webGl.deleteTexture(this.outputTexture);
}
if (this.buffer) {
this._webGl.deleteBuffer(this.buffer);
}
if (this.framebuffer) {
this._webGl.deleteFramebuffer(this.framebuffer);
}
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
var keys = Object.keys(this.textureCache);
for (var i = 0; i < keys.length; i++) {
var name = keys[i];
this._webGl.deleteTexture(this.textureCache[name]);
}
if (this.subKernelOutputTextures) {
for (var _i3 = 0; _i3 < this.subKernelOutputTextures.length; _i3++) {
this._webGl.deleteTexture(this.subKernelOutputTextures[_i3]);
}
}
if (removeCanvasReferences) {
var idx = canvases.indexOf(this._canvas);
if (idx >= 0) {
canvases[idx] = null;
maxTexSizes[idx] = null;
}
}
delete this._webGl;
}
}]);
return WebGLKernel;
@ -5369,7 +5447,6 @@ var GPU = function (_GPUCore) {
} else {
detectedMode = mode || 'gpu';
}
_this.kernels = [];
var runnerSettings = {
@ -5567,6 +5644,25 @@ var GPU = function (_GPUCore) {
value: function getWebGl() {
return this._webGl;
}
}, {
key: 'destroy',
value: function destroy() {
var kernels = this.kernels;
var destroyWebGl = !this._webGl && kernels.length && kernels[0]._webGl;
for (var i = 0; i < this.kernels.length; i++) {
this.kernels[i].destroy(true);
}
if (destroyWebGl) {
destroyWebGl.OES_texture_float = null;
destroyWebGl.OES_texture_float_linear = null;
destroyWebGl.OES_element_index_uint = null;
destroyWebGl.getExtension('WEBGL_lose_context').loseContext();
}
}
}]);
return GPU;
@ -5611,8 +5707,6 @@ var _createClass = function () { function defineProperties(target, props) { for
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var gpu = null;
module.exports = function () {
function Texture(texture, size, dimensions, output, webGl) {
@ -6002,9 +6096,10 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function () {
});
var x = gpu.createKernel(function () {
return 1;
}, {
output: [2],
@ -6014,7 +6109,7 @@ var Utils = function (_UtilsCore) {
})();
_isFloatReadPixelsSupported = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupported;
}
@ -6027,9 +6122,10 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl2-validator'
}).createKernel(function () {
});
var x = gpu.createKernel(function () {
return 1;
}, {
output: [2],
@ -6039,7 +6135,7 @@ var Utils = function (_UtilsCore) {
})();
_isFloatReadPixelsSupportedWebGL2 = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupportedWebGL2;
}
@ -6052,16 +6148,17 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function (v1, v2) {
});
var x = gpu.createKernel(function (v1, v2) {
return v1[this.thread.x] / v2[this.thread.x];
}, {
output: [1]
})([6, 6030401], [3, 3991]);
_hasIntegerDivisionAccuracyBug = x[0] !== 2 || x[1] !== 1511;
gpu.destroy();
return _hasIntegerDivisionAccuracyBug;
}
}, {

15
bin/gpu.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -459,6 +459,29 @@ module.exports = function () {
value: function addNativeFunction(name, source) {
this.functionBuilder.addNativeFunction(name, source);
}
/**
*
* Destroys all memory associated with this kernel
*
* @name destroy
* @function
* @memberOf KernelBase#
*
* * @param {Boolean} removeCanvasReferences remve any associated canvas references?
*
*/
}, {
key: 'destroy',
value: function destroy() {
if (this.subKernels) {
for (var i = 0; i < this.subKernels.length; i++) {
this.subKernels[i].destroy();
}
}
console.log('destroy kernel');
}
}]);
return KernelBase;

View File

@ -1,5 +1,7 @@
'use strict';
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@ -14,6 +16,8 @@ var Texture = require('../../core/texture');
var fragShaderString = require('./shader-frag');
var vertShaderString = require('./shader-vert');
var kernelString = require('./kernel-string');
// TODO: not fully worked out what these are for. they can leak...
var canvases = [];
var maxTexSizes = {};
@ -75,6 +79,8 @@ module.exports = function (_KernelBase) {
_this.argumentsLength = 0;
_this.compiledFragShaderString = null;
_this.compiledVertShaderString = null;
_this.fragShader = null;
_this.vertShader = null;
_this.drawBuffersMap = null;
_this.outputTexture = null;
_this.maxTexSize = null;
@ -198,6 +204,17 @@ module.exports = function (_KernelBase) {
}, {
key: 'build',
value: function build() {
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
this.validateOptions();
this.setupParams(arguments);
this.updateMaxTexSize();
@ -219,11 +236,14 @@ module.exports = function (_KernelBase) {
var vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, compiledVertShaderString);
gl.compileShader(vertShader);
if (this.vertShader) {}
this.vertShader = vertShader;
var compiledFragShaderString = this._getFragShaderString(arguments);
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, compiledFragShaderString);
gl.compileShader(fragShader);
this.fragShader = fragShader;
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
console.log(compiledVertShaderString);
@ -1445,6 +1465,53 @@ module.exports = function (_KernelBase) {
value: function addFunction(fn) {
this.functionBuilder.addFunction(null, fn);
}
}, {
key: 'destroy',
value: function destroy(removeCanvasReferences) {
_get(WebGLKernel.prototype.__proto__ || Object.getPrototypeOf(WebGLKernel.prototype), 'destroy', this).call(this);
if (this.outputTexture) {
this._webGl.deleteTexture(this.outputTexture);
}
if (this.buffer) {
this._webGl.deleteBuffer(this.buffer);
}
if (this.framebuffer) {
this._webGl.deleteFramebuffer(this.framebuffer);
}
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
var keys = Object.keys(this.textureCache);
for (var i = 0; i < keys.length; i++) {
var name = keys[i];
this._webGl.deleteTexture(this.textureCache[name]);
}
if (this.subKernelOutputTextures) {
for (var _i3 = 0; _i3 < this.subKernelOutputTextures.length; _i3++) {
this._webGl.deleteTexture(this.subKernelOutputTextures[_i3]);
}
}
if (removeCanvasReferences) {
var idx = canvases.indexOf(this._canvas);
if (idx >= 0) {
canvases[idx] = null;
maxTexSizes[idx] = null;
}
}
delete this._webGl;
}
}]);
return WebGLKernel;

30
dist/core/gpu.js vendored
View File

@ -50,7 +50,6 @@ var GPU = function (_GPUCore) {
} else {
detectedMode = mode || 'gpu';
}
_this.kernels = [];
var runnerSettings = {
@ -424,6 +423,35 @@ var GPU = function (_GPUCore) {
value: function getWebGl() {
return this._webGl;
}
/**
*
* Destroys all memory associated with gpu.js & the webGl if we created it
*
* @name destroy
* @function
* @memberOf GPU#
*
*
*/
}, {
key: 'destroy',
value: function destroy() {
var kernels = this.kernels;
var destroyWebGl = !this._webGl && kernels.length && kernels[0]._webGl;
for (var i = 0; i < this.kernels.length; i++) {
this.kernels[i].destroy(true); // remove canvas if exists
}
if (destroyWebGl) {
destroyWebGl.OES_texture_float = null;
destroyWebGl.OES_texture_float_linear = null;
destroyWebGl.OES_element_index_uint = null;
destroyWebGl.getExtension('WEBGL_lose_context').loseContext();
}
}
}]);
return GPU;

View File

@ -4,8 +4,6 @@ var _createClass = function () { function defineProperties(target, props) { for
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var gpu = null;
module.exports = function () {
/**

21
dist/core/utils.js vendored
View File

@ -372,9 +372,10 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function () {
});
var x = gpu.createKernel(function () {
return 1;
}, {
output: [2],
@ -384,7 +385,7 @@ var Utils = function (_UtilsCore) {
})();
_isFloatReadPixelsSupported = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupported;
}
@ -408,9 +409,10 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl2-validator'
}).createKernel(function () {
});
var x = gpu.createKernel(function () {
return 1;
}, {
output: [2],
@ -420,7 +422,7 @@ var Utils = function (_UtilsCore) {
})();
_isFloatReadPixelsSupportedWebGL2 = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupportedWebGL2;
}
@ -444,9 +446,10 @@ var Utils = function (_UtilsCore) {
}
var GPU = require('../index');
var x = new GPU({
var gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function (v1, v2) {
});
var x = gpu.createKernel(function (v1, v2) {
return v1[this.thread.x] / v2[this.thread.x];
}, {
output: [1]
@ -455,7 +458,7 @@ var Utils = function (_UtilsCore) {
// have we not got whole numbers for 6/3 or 6030401/3991
// add more here if others see this problem
_hasIntegerDivisionAccuracyBug = x[0] !== 2 || x[1] !== 1511;
gpu.destroy();
return _hasIntegerDivisionAccuracyBug;
}
}, {

View File

@ -393,4 +393,23 @@ module.exports = class KernelBase {
addNativeFunction(name, source) {
this.functionBuilder.addNativeFunction(name, source);
}
/**
*
* Destroys all memory associated with this kernel
*
* @name destroy
* @function
* @memberOf KernelBase#
*
* * @param {Boolean} removeCanvasReferences remve any associated canvas references?
*
*/
destroy() {
if (this.subKernels) {
for (let i = 0; i < this.subKernels.length; i++) {
this.subKernels[i].destroy();
}
}
}
};

View File

@ -55,6 +55,8 @@ module.exports = class WebGLKernel extends KernelBase {
this.argumentsLength = 0;
this.compiledFragShaderString = null;
this.compiledVertShaderString = null;
this.fragShader = null;
this.vertShader = null;
this.drawBuffersMap = null;
this.outputTexture = null;
this.maxTexSize = null;
@ -169,6 +171,17 @@ module.exports = class WebGLKernel extends KernelBase {
*/
build() {
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
this.validateOptions();
this.setupParams(arguments);
this.updateMaxTexSize();
@ -190,11 +203,16 @@ module.exports = class WebGLKernel extends KernelBase {
const vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, compiledVertShaderString);
gl.compileShader(vertShader);
if (this.vertShader) {
}
this.vertShader = vertShader;
const compiledFragShaderString = this._getFragShaderString(arguments);
const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, compiledFragShaderString);
gl.compileShader(fragShader);
this.fragShader = fragShader;
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
console.log(compiledVertShaderString);
@ -1401,4 +1419,50 @@ module.exports = class WebGLKernel extends KernelBase {
addFunction(fn) {
this.functionBuilder.addFunction(null, fn);
}
destroy(removeCanvasReferences) {
super.destroy();
if (this.outputTexture) {
this._webGl.deleteTexture(this.outputTexture);
}
if (this.buffer) {
this._webGl.deleteBuffer(this.buffer);
}
if (this.framebuffer) {
this._webGl.deleteFramebuffer(this.framebuffer);
}
if (this.vertShader) {
this._webGl.deleteShader(this.vertShader);
}
if (this.fragShader) {
this._webGl.deleteShader(this.fragShader);
}
if (this.program) {
this._webGl.deleteProgram(this.program);
}
var keys = Object.keys(this.textureCache);
for (var i = 0; i < keys.length; i++) {
const name = keys[i];
this._webGl.deleteTexture(this.textureCache[name]);
}
if (this.subKernelOutputTextures) {
for (let i = 0; i < this.subKernelOutputTextures.length; i++) {
this._webGl.deleteTexture(this.subKernelOutputTextures[i]);
}
}
if (removeCanvasReferences) {
let idx = canvases.indexOf(this._canvas);
if (idx >= 0) {
canvases[idx] = null;
maxTexSizes[idx] = null;
}
}
delete this._webGl;
}
};

View File

@ -37,7 +37,6 @@ class GPU extends GPUCore {
} else {
detectedMode = mode || 'gpu';
}
this.kernels = [];
const runnerSettings = {
@ -382,6 +381,33 @@ class GPU extends GPUCore {
getWebGl() {
return this._webGl;
}
/**
*
* Destroys all memory associated with gpu.js & the webGl if we created it
*
* @name destroy
* @function
* @memberOf GPU#
*
*
*/
destroy() {
const {
kernels
} = this;
const destroyWebGl = !this._webGl && kernels.length && kernels[0]._webGl;
for (let i = 0; i < this.kernels.length; i++) {
this.kernels[i].destroy(true); // remove canvas if exists
}
if (destroyWebGl) {
destroyWebGl.OES_texture_float = null;
destroyWebGl.OES_texture_float_linear = null;
destroyWebGl.OES_element_index_uint = null;
destroyWebGl.getExtension('WEBGL_lose_context').loseContext();
}
}
};
// This ensure static methods are "inherited"

View File

@ -1,7 +1,5 @@
'use strict';
let gpu = null;
module.exports = class Texture {
/**
@ -53,5 +51,6 @@ module.exports = class Texture {
*/
delete() {
return this.webGl.deleteTexture(this.texture);
}
};

View File

@ -322,9 +322,10 @@ class Utils extends UtilsCore {
}
const GPU = require('../index');
const x = new GPU({
const gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function() {
});
const x = gpu.createKernel(function() {
return 1;
}, {
output: [2],
@ -334,7 +335,7 @@ class Utils extends UtilsCore {
})();
_isFloatReadPixelsSupported = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupported;
}
@ -355,9 +356,10 @@ class Utils extends UtilsCore {
}
const GPU = require('../index');
const x = new GPU({
const gpu = new GPU({
mode: 'webgl2-validator'
}).createKernel(function() {
});
const x = gpu.createKernel(function() {
return 1;
}, {
output: [2],
@ -367,7 +369,7 @@ class Utils extends UtilsCore {
})();
_isFloatReadPixelsSupportedWebGL2 = x[0] === 1;
gpu.destroy();
return _isFloatReadPixelsSupportedWebGL2;
}
@ -388,9 +390,10 @@ class Utils extends UtilsCore {
}
const GPU = require('../index');
const x = new GPU({
const gpu = new GPU({
mode: 'webgl-validator'
}).createKernel(function(v1, v2) {
});
const x = gpu.createKernel(function(v1, v2) {
return v1[this.thread.x] / v2[this.thread.x];
}, {
output: [1]
@ -399,7 +402,7 @@ class Utils extends UtilsCore {
// have we not got whole numbers for 6/3 or 6030401/3991
// add more here if others see this problem
_hasIntegerDivisionAccuracyBug = (x[0] !== 2 || x[1] !== 1511);
gpu.destroy();
return _hasIntegerDivisionAccuracyBug;
}

View File

@ -53,7 +53,8 @@
<script src="issues/130-typed-array.js"></script>
<script src="issues/147-missing-constant.js"></script>
<script src="issues/152-for-vars.js"></script>
<script src="issues/159-3d.js"></script>
<script src="issues/159-3d.js"></script>
<script src="issues/174-webgl-context-warning.js"></script>
<script src="issues/195-read-from-texture2d.js"></script>
<script src="issues/207-same-function-reuse.js"></script>
<script src="issues/212-funky-function-support.js"></script>

View File

@ -0,0 +1,77 @@
(function() {
// unfortunately there is a bit of a manual process to check this properly!
// so check there are no warnings in the log when running ALL tests
// 2 check heap snapshots
// run the following code in the console
// function run() {
// var gpu = new GPU({ mode: 'webgl' });
// var kernel1 = gpu.createKernel(function() {
// return this.thread.y * this.thread.x;
// }, {
// output: [1024, 1024]
// })
// kernel1();
// gpu.destroy();
// gpu = new GPU({ mode: 'webgl2' });
// var kernel2 = gpu.createKernel(function() {
// return this.thread.y * this.thread.x;
// }, {
// output: [1024, 1024]
// })
// kernel2();
// gpu.destroy();
// }
// then do a heap snapshot
// then run() in the console
// do another heap snapshot and compare the differences...
//
var input = [[0, 1, 2], [3, 4, 5], [6, 7, 8]];
function manyKernels(mode, assert) {
var done = assert.async();
var thisIndex = 0;
for (var i = 0; i < 20; i++) {
setTimeout(function() {
// breakpoint 1 here
var gpu = new GPU({ mode });
var kernel = gpu.createKernel(function(inp) {
return inp[this.thread.y][this.thread.x];
}, {
output: [3, 3]
});
var kernel2 = gpu.createKernel(function() {
return this.thread.y * this.thread.x;
}, {
output: [1024, 1024]
}).setOutputToTexture(true);
kernel(input);
kernel2();
if (kernel._webGl !== kernel2._webGl) {
assert.ok(false, "webgls should be the same object")
}
gpu.destroy();
thisIndex++;
if (thisIndex > 19) {
setTimeout(function() {
// breakpoint 2 here
assert.ok(true)
done()
}, 0)
}
}, 0);
}
}
QUnit.test('Issue #174 - webgl context leak - !!! do manual tests !!! (webgl)', function(assert) {
manyKernels('webgl', assert);
});
QUnit.test('Issue #174 - webgl context leak - !!! do manual tests !!! (webgl2)', function(assert) {
manyKernels('webgl2', assert);
});
})()