如何释放和垃圾收集WebGL上下文?

Afr*_*Afr 9 javascript free garbage-collection webgl destroy

我正在为Web和移动开发WebGL应用程序.我经常使用硬刷新来测试我的WebGL实现的结果.视图尝试后,我收到错误:

Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.
Run Code Online (Sandbox Code Playgroud)

这不会出现在新启动的浏览器上,而是在多次刷新网站后出现.我想WebGL上下文没有完成,发布,销毁,清理,正确释放.

我怎样才能做到这一点?

Khronos Group在这里创建了一个用于释放和垃圾收集WebGL上下文的测试套件:https://www.khronos.org/registry/webgl/sdk/tests/conformance/context/context-creation-and-destruction.html(注意:这个可能会崩溃您的浏览器!)

测试通过PASSTEST COMPLETE,所以基本上测试没有检测到任何问题.但是,打开JavaScript控制台,它会读取33个实例:

Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.
Run Code Online (Sandbox Code Playgroud)

这是浏览器如何处理WebGL的错误吗?或者我做错了什么?我从没想过要释放任何WebGL上下文.

我正在使用Firefox Developer Edition 48.0a2和Firefox 46.0.1.

如何释放和垃圾收集WebGL上下文?

gma*_*man 5

我想也许我误解了你的问题

您说您正在努力刷新。表示您要在浏览器中按“刷新”?在那种情况下,我首先禁用所有扩展,然后查看问题是否仍然存在。如果是,我会向mozilla提交错误

否则,如果您尝试释放画布并创建已知的画布并希望很好地进行垃圾收集..这是我在重新阅读您的问题之前写的答案


简短的答案是您不能强制垃圾回收。您最好重新使用相同的画布。

这里有一个解决方案,可以释放所有数据并重置画布

使用后如何从GPU清理WebGL canvas上下文并从其中卸载?

但是,在您的特定情况下,您是否100%确定不保留对WebGL上下文或画布的某些引用?例如,如果您这样做

canvas.addEventListener('click', function(..) {});
Run Code Online (Sandbox Code Playgroud)

您刚刚制作了一个永远无法进行垃圾收集的画布。它具有附加的事件侦听器功能。您没有办法删除该功能,因为您没有对其进行引用。您需要删除所有侦听器,这只是泄漏引用的多种方式中的一个示例。

有无数种方式意外保留对HTML元素(如canvas以及WebGL对象)的引用。保留超过零个引用,并且永远不会对其进行垃圾回收。

这是发现泄漏的一些提示

另一方面,如果是我,我会尝试重新使用画布。为了确保释放所有内容,我可以调用自己的创建/删除函数来跟踪所有资源。例

var textures = [];
function createTexture(gl) {
  var tex = gl.createTexture();
  textures.push(txt);
}

function deleteTexture(gl, tex) {
  gl.deleteTexture(tex);
  textures.splice(textures.indexOf(tex), 1);
}
Run Code Online (Sandbox Code Playgroud)

现在,由于我正在跟踪所有纹理,因此可以轻松删除所有剩余的纹理

while (textures.length) {
  gl.deleteTexture(textures.pop());
}
Run Code Online (Sandbox Code Playgroud)