mirror of
https://github.com/gpujs/gpu.js.git
synced 2026-01-25 16:08:02 +00:00
fix leaking WegGl contexts
This commit is contained in:
parent
03077cedd1
commit
92612c1c2f
@ -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
2
bin/gpu-core.min.js
vendored
@ -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
|
||||
|
||||
123
bin/gpu.js
123
bin/gpu.js
@ -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
15
bin/gpu.min.js
vendored
File diff suppressed because one or more lines are too long
23
dist/backend/kernel-base.js
vendored
23
dist/backend/kernel-base.js
vendored
@ -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;
|
||||
|
||||
67
dist/backend/web-gl/kernel.js
vendored
67
dist/backend/web-gl/kernel.js
vendored
@ -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
30
dist/core/gpu.js
vendored
@ -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;
|
||||
|
||||
2
dist/core/texture.js
vendored
2
dist/core/texture.js
vendored
@ -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
21
dist/core/utils.js
vendored
@ -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;
|
||||
}
|
||||
}, {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
@ -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"
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
};
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
77
test/issues/174-webgl-context-warning.js
Normal file
77
test/issues/174-webgl-context-warning.js
Normal 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);
|
||||
});
|
||||
})()
|
||||
Loading…
x
Reference in New Issue
Block a user