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

查看:42
本文介绍了使用后如何从 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 来释放您的所有资源并取消绑定所有绑定点.这意味着对于所有具有 null 的目标上的每个纹理单元调用 gl.bindTexture,对于数组、帧缓冲区和渲染缓冲区也是如此.

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.

另见@Johan's answer about loseContext

Also see @Johan's answer about loseContext

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

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