WebGL组件在React中如何正确销毁避免内存泄漏?
我在React里封装了一个WebGL画布组件,每次切换页面时发现GPU内存没释放,Chrome任务管理器里显存一直涨。
试过在useEffect返回函数里调用gl.getExtension(‘WEBGL_lose_context’)?.loseContext(),但好像没用。是不是应该手动删除所有buffer和texture?
现在组件卸载时的清理代码是这样:
useEffect(() => {
const canvas = ref.current;
const gl = canvas.getContext('webgl');
// ...初始化逻辑
return () => {
gl.getExtension('WEBGL_lose_context')?.loseContext();
};
}, []);
loseContext并不保险,这也不是 WebGL 规范推荐的清理方式。根据 WebGL 的官方文档,所有创建的资源都必须显式调用对应的 delete 方法。你遇到的显存不释放,大概率是因为 JS 层面的对象被 GC 了,但底层的 GPU 资源还在。浏览器不会因为你丢掉了 JS 引用就立马去释放显存,必须得你明确告诉 GL 上下文“这个东西我不要了”。
标准写法是把你创建的所有 buffer、texture、shader、program 和 renderbuffer 都存起来,在组件卸载的时候遍历删除。另外,别忘了把 canvas 元素的引用也清空,断开和 GL 上下文的联系。
只有这样严格按规范来,Chrome 任务管理器里的显存才会乖乖降下来。偷懒只调用 loseContext,有时候浏览器并不买账。