【发布时间】:2019-05-01 16:05:00
【问题描述】:
我有一个巨大的着色器,它需要一分钟多的时间来编译,它在整个过程中完全停止了整个浏览器。据我所知,着色器编译不能异步进行,因此您可以在等待编译完成时运行其他 WebGL 命令。
我已经尝试了以下方法:
- 暂时不要使用特定的着色器 - 这不起作用,因为大多数其他 WebGL 命令将等待它完成,即使该着色器程序从未激活过
- 使用另一个上下文 - 与上面相同,但即使来自另一个上下文的 WebGL 命令也会导致停顿
- 在 web worker 中使用 OffscreenCanvas - 这也不能避免停顿,即使它在 worker 中,它也会停顿整个浏览器。即使我在命令链接程序后等待几分钟以发出任何其他 WebGL 命令,浏览器也会停止(好像在那段时间没有发生任何事情)
另一个问题是它有时会导致 WebGL 崩溃(上下文丢失),这会导致页面(或工作线程)上的所有上下文崩溃。
有什么办法可以避免浏览器卡住吗?
我可以将我的着色器拆分为多个部分并分别编译吗?
这就是我的程序初始化的样子,可以以某种方式更改吗?
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
let program = gl.createProgram();
gl.shaderSource(vertexShader, vertexSource);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
let status = gl.getProgramParameter(program, gl.LINK_STATUS);
let programLog = gl.getProgramInfoLog(program);
在调用 linkProgram 后等待几分钟甚至在工作人员中也无济于事。
最后要注意的是:我可以有例如使用不受此影响的 OpenGL 运行的 windows 游戏(游戏正在运行,我开始在浏览器中编译此着色器,并且游戏在浏览器停止时继续运行正常)
【问题讨论】:
-
您是在拨打
gl.linkProgram之后再拨打gl.flush然后等待的吗? -
@gman 调用
gl.flush会立即导致停顿。我不明白为什么它在网络工作者中完成时会冻结整个浏览器。所有 WebGL 上下文是否最终都为选项卡/浏览器使用相同的上下文?如果我会遇到相同的编译时间,例如C/C++ 应用程序会影响其他线程吗? (我可能会尝试,但它肯定不会影响其他应用程序,所以我希望在不同线程中创建的两个 OpenGL 上下文不应该以这种方式相互影响)。