WebGL上下文丢失并未恢复

6
我遇到了关于webgl上下文丢失/恢复的问题。
我的应用程序非常重,包含大量信息、图表、列表和地图。
在地图中,我使用webGL以获得最佳性能。我的代码可以正确处理上下文丢失和恢复。
我开始一个耗时的操作,导致从服务器加载数据、解析数据等。这有时会导致浏览器丢失我的webgl上下文。问题是上下文永远无法恢复。当我再次执行此大型操作时,我才能获得恢复事件。
在我看来,这与内存和垃圾回收释放时间有关。
但我真的不知道该怎么做,如何解决这个问题。
2个回答

5
处理丢失的一种方法是重新创建画布并重新初始化GL部分的应用程序。最终,所有资源都已消失,因此上下文重新创建的额外开销不应太麻烦,并且可以在webglcontextlost事件到达时立即采取行动。(虽然不确定这是否是最佳方法...)
关于Raziza答案中的WEBGL_lose_context的评论:不要像您在那里提出的那样使用此选项。该扩展仅是调试工具,应仅用于模拟此行为。
另请参见:https://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/

0
发现了一种手动调用恢复上下文的方法。不知道这样做是否好/明智,但对我来说它是有效的。
我们使用扩展WEBGL_lose_context来实现。 MDN参考
// Loading the extension
var ext = gl.getExtension("WEBGL_lose_context"); 

...
// This code in the context lost event, wait 3 secs for forcing 
// restore context
var restoreTimeout = setTimeout(function() { 
     ext.restoreContext(); 
}, 3000);

...
// This code in restore context event
// incase we got restore not from my timeout, i'm canceling it
restoreTimeout && clearTimeout(restoreTimeout);

1
我在NW.js中遇到了类似的情况,在webglcontextlost事件处理程序中调用"event.preventDefault()"并没有像预期的那样恢复上下文,使用"ext.restoreContext()"可以工作,但只有当你在触发上下文丢失事件之前设置"ext = gl.getExtension("WEBGL_lose_context");"时才可以。(否则调用该扩展会返回"null") - Jaruba
我错了!.restoreContext()只有在通过手动使用.loseContext()丢失上下文时才起作用,否则(在自然情况下)它不会做任何事情。它专门用于模拟上下文的丢失。来自文档如果上下文不是通过loseContext()丢失的,则生成INVALID_OPERATION错误。 - Jaruba
另一种失去和恢复上下文的方法是在DOM中添加一个按钮,创建新画布并在循环中获取WebGL上下文。根据我在Chrome中检查的情况,在总共15个上下文之后,最旧/未使用的上下文将丢失,并且一旦其他上下文(我们的主要上下文)需要显示,它就会被恢复。 - Raziza O
1
我的问题与自然地丢失上下文有关,这意味着上下文丢失了(很可能)是因为其他应用程序正在请求更多资源,由于WebGL是流体的,它无法保持在一个位置,所以我们会得到“上下文丢失”错误。通常,按照文档中的说明,只需在上下文丢失事件中执行event.preventDefault()即可轻松解决。但是它不起作用。除非您在此之前手动调用.loseContext(),否则.restoreContext()将完全无效。 - Jaruba
我甚至尝试使用Node.cloneNode()来克隆画布以请求新的WebGL上下文,但这也没有起作用。我坚信这是Chrome的一个bug,目前绝对无法恢复上下文。我已经尝试了一个月内能想到的所有方法,但仍未找到任何解决方案。向DOM添加按钮是不可接受的,因为我们正在为NW.js/Electron开发视频播放器,该播放器与VLC二进制文件绑定,并将视频帧绘制到画布中,失去WebGL上下文会停止视频传输。 - Jaruba
1
也许我没有完全理解你的意思,但是当Chrome/其他浏览器因为需要太多资源而失去上下文时,它基本上会失去所有数据。这意味着缓冲区、着色器、纹理、状态以及您使用或创建的所有其他内容都将被删除。完全重置。当上下文恢复(每当浏览器想要绘制您的上下文时),您将收到事件,并且必须再次创建/上传所有数据到GPU,这意味着着色器、纹理等。我建议的按钮仅用于调试您的上下文代码的丢失和恢复。 - Raziza O

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接