如何在使用后从GPU中清理和卸载WebGL画布上下文? [英] How do I clean up and unload a WebGL canvas context from GPU after use?

查看:2491
本文介绍了如何在使用后从GPU中清理和卸载WebGL画布上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How do you clean up a WebGL context program and unload the program, buffers and everything from the GPU and dom-element?

我想确保我们不是乱抛垃圾。

I'd like to make sure we're not littering.

此外,如果可能的话,重用画布会更好(我不知道是否 2d webgl 上下文)。

Also it'd be nice to reuse the canvas if possible (and I don't know if it'd be 2d or webgl context).

推荐答案

每次引用您的gl上下文和所有gl对象和画布,并从DOM中删除画布。不幸的是,因为JavaScript是垃圾收集,所以不知道什么时候浏览器会释放内存。有一些一致性测试,试图测试他们这样做正确,但如果你不想只是希望和祈祷然后....

You can just lose every reference to your gl context and all gl objects and the canvas and remove the canvas from the DOM. Unfortunately, because JavaScript is garbage collected there's no knowing when the browser will actually free the memory. There are some conformance tests to try to test they do this correctly but if you don't want to just hope and pray then ....

要释放所有的资源通过在您创建的所有内容上调用 gl.deleteXXX ,并解除绑定所有绑定点。这意味着每个纹理单元在所有目标上调用gl.bindTexture,使用null,与数组,framebuffers和renderbuffers相同。

To free all your resources by calling gl.deleteXXX on everything you created and unbind all bind points. That means for every texture unit call gl.bindTexture on all targets with null, the same with arrays, framebuffers and renderbuffers.

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 (不允许为零),然后再将其删除。

Because you can't bind null to an attribute you could set the size of all your buffers to 1 (zero is not allowed) before you delete them. Either that or make a new buffer and assign it to all attributes.

第一个例子

// 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);

或创建一个新缓冲区并将其分配给所有属性

Or make a new buffer and assign it to all attributes

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);
}

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

This will unbind the old buffers from the attributes.

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

Finally set the canvas size to 1x1 pixel.

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

这不是一个完美的解决方案,但它会立即释放几个k的内存,对于无法控制的垃圾回收。

It's not a perfect solution but it will immediately free all but a few k of memory immediately, no waiting for garbage collection which is out of your control.

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

As for reusing the canvas from scratch you can't. The canvas will always have the same context you first asked it for.

这篇关于如何在使用后从GPU中清理和卸载WebGL画布上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆