Skip to content

Commit a1b80b7

Browse files
Merge pull request #527 from gpujs/523-texture-memory
fix: #523 cleanup texture memory
2 parents 27dea69 + c338399 commit a1b80b7

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

src/backend/web-gl/kernel.js

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class WebGLKernel extends GLKernel {
163163
this.threadDim = null;
164164
this.framebuffer = null;
165165
this.buffer = null;
166-
this.textureCache = {};
166+
this.textureCache = [];
167167
this.programUniformLocationCache = {};
168168
this.uniform1fCache = {};
169169
this.uniform1iCache = {};
@@ -428,7 +428,7 @@ class WebGLKernel extends GLKernel {
428428
kernel: this,
429429
strictIntegers: this.strictIntegers,
430430
onRequestTexture: () => {
431-
return this.context.createTexture();
431+
return this.createTexture();
432432
},
433433
onRequestIndex: () => {
434434
return textureIndexes++;
@@ -446,6 +446,12 @@ class WebGLKernel extends GLKernel {
446446
}
447447
}
448448

449+
createTexture() {
450+
const texture = this.context.createTexture();
451+
this.textureCache.push(texture);
452+
return texture;
453+
}
454+
449455
setupConstants(args) {
450456
const { context: gl } = this;
451457
this.kernelConstants = [];
@@ -479,7 +485,7 @@ class WebGLKernel extends GLKernel {
479485
kernel: this,
480486
strictIntegers: this.strictIntegers,
481487
onRequestTexture: () => {
482-
return this.context.createTexture();
488+
return this.createTexture();
483489
},
484490
onRequestIndex: () => {
485491
return textureIndexes++;
@@ -711,7 +717,7 @@ class WebGLKernel extends GLKernel {
711717
_setupOutputTexture() {
712718
const gl = this.context;
713719
const texSize = this.texSize;
714-
const texture = this.outputTexture = this.context.createTexture();
720+
const texture = this.outputTexture = this.createTexture();
715721
gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount);
716722
gl.bindTexture(gl.TEXTURE_2D, texture);
717723
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
@@ -768,7 +774,7 @@ class WebGLKernel extends GLKernel {
768774
this.drawBuffersMap = [gl.COLOR_ATTACHMENT0];
769775
this.subKernelOutputTextures = [];
770776
for (let i = 0; i < this.subKernels.length; i++) {
771-
const texture = this.context.createTexture();
777+
const texture = this.createTexture();
772778
this.subKernelOutputTextures.push(texture);
773779
this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1);
774780
gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i);
@@ -1465,9 +1471,6 @@ class WebGLKernel extends GLKernel {
14651471
}
14661472

14671473
destroy(removeCanvasReferences) {
1468-
if (this.outputTexture) {
1469-
this.context.deleteTexture(this.outputTexture);
1470-
}
14711474
if (this.buffer) {
14721475
this.context.deleteBuffer(this.buffer);
14731476
}
@@ -1483,18 +1486,9 @@ class WebGLKernel extends GLKernel {
14831486
if (this.program) {
14841487
this.context.deleteProgram(this.program);
14851488
}
1486-
1487-
const keys = Object.keys(this.textureCache);
1488-
1489-
for (let i = 0; i < keys.length; i++) {
1490-
const name = keys[i];
1491-
this.context.deleteTexture(this.textureCache[name]);
1492-
}
1493-
1494-
if (this.subKernelOutputTextures) {
1495-
for (let i = 0; i < this.subKernelOutputTextures.length; i++) {
1496-
this.context.deleteTexture(this.subKernelOutputTextures[i]);
1497-
}
1489+
while (this.textureCache.length > 0) {
1490+
const texture = this.textureCache.pop();
1491+
this.context.deleteTexture(texture);
14981492
}
14991493
if (removeCanvasReferences) {
15001494
const idx = canvases.indexOf(this.canvas);
@@ -1535,4 +1529,4 @@ class WebGLKernel extends GLKernel {
15351529

15361530
module.exports = {
15371531
WebGLKernel
1538-
};
1532+
};

src/backend/web-gl2/kernel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ class WebGL2Kernel extends WebGLKernel {
274274
this.drawBuffersMap = [gl.COLOR_ATTACHMENT0];
275275
this.subKernelOutputTextures = [];
276276
for (let i = 0; i < this.subKernels.length; i++) {
277-
const texture = this.context.createTexture();
277+
const texture = this.createTexture();
278278
this.subKernelOutputTextures.push(texture);
279279
this.drawBuffersMap.push(gl.COLOR_ATTACHMENT0 + i + 1);
280280
gl.activeTexture(gl.TEXTURE0 + this.constantTextureCount + this.argumentTextureCount + i);

test/features/destroy.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const { assert, skip, test, module: describe } = require('qunit');
2-
const { GPU } = require('../../src');
2+
const { GPU, WebGLKernel } = require('../../src');
33
const sinon = require('sinon');
44

55
describe('features: destroy');
@@ -55,3 +55,31 @@ test('with destroy context', (t) => {
5555
const done = t.async();
5656
testWithDestroyContext(done);
5757
});
58+
59+
60+
function testTexturesAreDestroyed(done, mode) {
61+
const mockTexture1 = {};
62+
const mockTexture2 = {};
63+
const mockTexture3 = {};
64+
const deleteTextureMock = sinon.spy();
65+
const mockContext = {
66+
deleteTexture: deleteTextureMock,
67+
};
68+
const mockKernelInstance = {
69+
textureCache: [mockTexture1, mockTexture2, mockTexture3],
70+
context: mockContext,
71+
destroyExtensions: () => {},
72+
};
73+
mockKernelInstance.destroy = WebGLKernel.prototype.destroy.bind(mockKernelInstance);
74+
GPU.prototype.destroy.call({ kernels: [mockKernelInstance] });
75+
setTimeout(() => {
76+
assert.equal(deleteTextureMock.callCount, 3);
77+
assert.ok(true);
78+
done();
79+
}, 2);
80+
}
81+
82+
test('textures are destroyed', (t) => {
83+
const done = t.async();
84+
testTexturesAreDestroyed(done);
85+
});

0 commit comments

Comments
 (0)