WebGL deleteBuffer内存泄漏

WebGL deleteBuffer leaking memory?

本文关键字:泄漏 内存 deleteBuffer WebGL      更新时间:2023-09-26

我有一个管理大量数据的WebGL应用程序。我在IE11上遇到过内存很快耗尽的问题(Chrome和FF没有出现这个问题)。然而,当我创建一些测试代码来隔离泄漏原因时,Chrome上的测试代码也会泄漏。进一步的测试表明,即使是Chrome在实际应用程序中也存在泄漏,或者看起来确实存在,但似乎不会像IE11那样崩溃。

以下是显示问题的测试代码:示例

基本上,我使用这个创建缓冲区:

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, bufferData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

对于我创建的每个缓冲区,我也会做出相应的调用来删除它,如下所示(必要时删除):

gl.deleteBuffer(buffer);

然而,从jsfiddle测试代码中可以看出,删除缓冲区似乎并不能释放浏览器使用的内存。即使缓冲区被删除,它也会很快耗尽内存。

显然,这是一个人为的例子,但它确实反映了我正在做的事情(即创建缓冲区,然后删除它们),但随着时间的推移,这似乎会导致内存无法释放。

我应该如何释放此内存以避免泄漏?有什么想法吗?

在动画循环中重复创建和删除缓冲区从来都不是一个好主意,因为这会导致视频内存碎片。视频内存不像Java或.NET那样由功能强大的垃圾收集器来管理,因为它会与性能形成强烈对比。在删除完整的GL上下文之前,使用"deleteBuffer"释放的内容实际上可能不会被释放用于新用途。

如果您需要使用大量动态变化的缓冲区,请使用gl.DYNAMIC_DRAW提示,这将导致驱动程序将缓冲区存储在CPU内存中,并在每次渲染时将其流式传输到GPU(当然会降低性能),或者继续重新使用缓冲区(可能建议过度配置其尺寸)。

许多专业的3D引擎对所有网格只使用一个大型顶点缓冲区对象,使用bufferSubData和带有偏移的绘图命令。

根据您对@mpfeferie的评论,听起来您的最佳选择是找到一个现成的(满足您需求的)objects pool,或者自己制作一个。

这个概念,如果不知道的话,在Pool_wiki上有一个非常清晰的解释。

如果可能的话,我会为缓冲区数组分配内存。这种保存"大"数据块的数组非常可怕。你永远无法确定他们到底为自己保留了多少空间。

此外,您可以重新检查是否没有留下任何被遗忘的变量引用。

如果您在预加载时有一些"空闲"时间,可以尝试每隔一段时间暂停渲染几分钟,这可能会帮助糟糕的GC完成任务。