如何在使用后从GPU清理和卸载WebGL画布上下文?

时间:2014-05-11 22:07:04

标签: javascript canvas webgl

如何清理WebGL上下文程序并从GPU和dom-element卸载程序,缓冲区和所有内容?

我想确保我们不乱扔垃圾。

如果可能的话,重复使用画布也是很好的(我不知道它是2d还是webgl上下文。)

2 个答案:

答案 0 :(得分:19)

您可以丢失对gl上下文和所有gl对象和画布的每个引用,并从DOM中删除画布。不幸的是,因为JavaScript被垃圾收集,所以不知道浏览器何时会实际释放内存。有一些一致性测试试图测试他们是否正确地做了这个,但如果你不想只是希望并祈祷......

通过在您创建的所有内容上调用gl.deleteXXX来释放所有资源,并取消绑定所有绑定点。这意味着对于每个纹理单元,在所有具有null的目标上调用gl.bindTexture,与数组,帧缓冲区和渲染缓冲区相同。

var numTextureUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
for (var unit = 0; unit < numTextureUnits; ++unit) {
  gl.activeTexture(gl.TEXTURE0 + unit);
  gl.bindTexture(gl.TEXTURE_2D, null);
  gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

// Delete all your resources
// Note!!!: You'd have to change this code to delete the resources YOU created.
gl.deleteTexture(someTexture);
gl.deleteTexture(someOtherTexture);
gl.deleteBuffer(someBuffer);
gl.deleteBuffer(someOtherBuffer);
gl.deleteRenderbuffer(someRenderbuffer);
gl.deleteFramebuffer(someFramebuffer);

因为您无法将null绑定到属性,所以您可以在删除它们之前将所有缓冲区的大小设置为1(不允许为零)。或者创建一个新缓冲区并将其分配给所有属性。

第一个

的例子
// set a buffer to 1 byte before deleting
// NOTE: You'd need to do this for ALL BUFFERS you created.
gl.bindBuffer(gl.ARRAY_BUFFER, someArrayBuffer);
gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW);
gl.deleteBuffer(someArrayBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, someElementArrayBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1, gl.STATIC_DRAW);
gl.deleteBuffer(someElementArrayBuffer);

或制作新缓冲区并将其分配给所有属性

var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var numAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
for (var attrib = 0; attrib < numAttributes; ++attrib) {
  gl.vertexAttribPointer(attrib, 1, gl.FLOAT, false, 0, 0);
}

这将从属性中解除旧缓冲区的绑定。

最后将画布大小设置为1x1像素。

gl.canvas.width = 1;
gl.canvas.height = 1;

它不是一个完美的解决方案,但它会立即释放除了几k内存之外的所有内存,而不是等待你无法控制的垃圾收集。

至于从头开始重新使用画布,你不能。画布将始终具有您首次要求的相同上下文。

另见@ Johan关于loseContext

的回答

答案 1 :(得分:7)

要丢失上下文,请使用扩展名WEBGL_lose_context作为

gl.getExtension('WEBGL_lose_context').loseContext();

请参阅https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context/loseContext