WebGL如何避免长着色器编译使选项卡停滞 [英] WebGL how to avoid long shader compile stalling a tab

查看:159
本文介绍了WebGL如何避免长着色器编译使选项卡停滞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个巨大的着色器,需要花费一分钟以上的时间进行编译,从而在整个过程中完全停滞了整个浏览器.据我所知,着色器编译不能异步进行,因此可以在等待编译完成时运行其他WebGL命令.

I have a giant shader that takes more than a minute to compile, which completely stalls whole browser during the process. As far as I know shader compilation cannot be made asynchronous, so you can run other WebGL commands while waiting for compilation to be done.

我已经尝试了以下方法:

I already tried the following:

  • 一段时间不使用该特定着色器-这是行不通的,因为大多数其他WebGL命令将等待其完成,即使该着色器程序从未处于活动状态
  • 使用另一个上下文-与上面相同,但是即使来自另一个上下文的WebGL命令也会导致停顿
  • 在Web worker中使用OffscreenCanvas -这也无法避免停顿,即使它在worker中,也会停滞整个浏览器.即使我在命令链接程序后等待几分钟以发出任何其他WebGL命令,浏览器也会停止运行(好像在此期间什么都没发生)
  • don't use that particular shader for some time - this doesn't work, because most other WebGL commands will wait for it to finish, even if that shader program is never made active
  • use another context - same as above, but even WebGL commands from another context will cause the stall
  • use OffscreenCanvas in web worker - this doesn't avoid the stall either, and even if it is in worker, it stalls whole browser. Even if I wait few minutes after command to link program to issue any other WebGL command, browser stalls (as if nothing was happening during that time)

另一个问题是,有时它会使WebGL(上下文丢失)崩溃,从而使页面(或工作线程)中的所有上下文崩溃.

Another problem is that it sometimes crashes WebGL (context loss), which crashes all contexts on page (or in worker).

有什么办法可以避免浏览器停顿吗?

Is there something I can do to avoid stalling browser?

我可以将着色器拆分为多个部分并分别编译吗?

Can I split my shader to multiple parts and compile them separately?

这是我的程序初始化的样子,它可以以某种方式更改吗?

This is how my program initialization looks like, can it be changed somehow?

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几分钟后等待,即使在工作人员中也无济于事.

Waiting after call to linkProgram for minutes doesn't help even in worker.

最后要注意的一点是:例如使用不受此影响的OpenGL运行的Windows游戏(游戏正在运行,我开始在浏览器中编译此着色器,并且当浏览器停止运行时,游戏仍然可以正常运行)

As a final thing to note: I can have e.g. windows game using OpenGL running that is not affected by this (game is running, I start compiling this shader in browser and game continues to run ok while browser stalls)

推荐答案

没有好的解决方案.

Windows上的浏览器使用DirectX,因为在许多计算机上默认情况下都不提供OpenGL,并且浏览器所需的许多其他功能与OpenGL不兼容.

Browsers on Windows use DirectX because OpenGL doesn't ship by default on many machines and because lots of other features needed for the browser are incompatible with OpenGL.

DirectX需要很长时间才能编译着色器.只有Microsoft可以解决此问题. Microsoft已为HLSL着色器编译器提供了源代码,但仅适用于DX12.

DirectX takes a long time to compile shaders. Only Microsoft can fix that. Microsoft has provided source to an HLSL shader compiler but it only works with DX12.

有人建议允许网页提供二进制着色器,但是由于两个非常重要的原因,这种情况永远不会发生

Some people suggest allowing webpages to provide binary shaders but that's never going to happen ever for 2 very important reasons

  1. 它们不是便携式的

  1. They aren't portable

一个网页必须提供100或1000多种二进制着色器.适用于每种类型的GPU *每种类型的驱动程序*每个平台(iOS,Android,PI,Mac,Windows,Linux,Fire等).网页应该加载到任何地方,因此着色器二进制文件不是Web的解决方案.

A webpage would have to provide 100s or 1000s of variations of binary shaders. One for every type of GPU * every type of driver * every platform (iOS, Android, PI, Mac, Windows, Linux, Fire, ...). Webpages are supposed to load everywhere so shader binaries are not solution for the web.

这将是一个巨大的安全问题.

It would be a huge security issue.

让用户下载分配给OS/GPU的随机二进制Blob来执行将是利用漏洞的巨大来源. 1

Having users download random binary blobs that are given to the OS/GPU to execute would be huge source for exploits.1

请注意,某些浏览器(尤其是Chrome)会在后台本地缓存着色器二进制文件,但这对首次编译没有帮助.

Note that some browsers (Chrome in particular) cache shader binaries locally behind the scenes but that doesn't help first time compilation.

因此,目前基本上没有解决方案.您可以制作更简单的着色器,也可以一次编译更少的着色器.人们要求使用异步扩展来编译着色器,但一直没有进展.

So basically at the moment there is no solution. You can make simpler shaders or compile less of them at once. People have asked for an async extension to compile shaders but there's been no movement.

这是2年前的主题 https://www.khronos.org/webgl/public-mailing-list/public_webgl/1702/msg00039.php

仅是个人观点,但我猜测异步扩展没有太多动作的原因是,它实现的工作量比听起来要多,并且存在许多具有复杂着色器的站点并且似乎可以正常工作.

Just a personal opinion but I'm guessing the reason there isn't much movement for an async extension it's way more work to implement than it sounds and that plenty of sites with complex shaders exist and seem to work.

1 作为文本GLSL传递给WebGL的着色器由浏览器编译,检查各种问题,如果任何WebGL规则被破坏,则拒绝它们,然后将它们重写为为了安全起见,请插入错误的解决方法,重新编写变量名,添加约束说明,有时展开循环,以确保您不会使驱动程序崩溃.您可以使用WEBGL_debug_shaders扩展名查看实际发送给驱动程序的着色器.

1The shaders you pass to WebGL as text GLSL are compiled by the browser, checked for all kinds of issues, rejected if any of the WebGL rules are broken, they are then re-written to be safe with bug workarounds inserted, variable names re-written, clamping instructions added, sometimes loops unrolled, all kinds of things to make sure you can't crash the driver. You can use WEBGL_debug_shaders extension to see the shader that's actually sent to the driver.

二进制着色器是您提供给驱动程序的Blob,由于它是驱动程序专有的二进制文件,因此您没有机会对其进行检查或验证其是否做得不好.没有关于其中的内容,格式的文档,它们可以随每个GPU和每个驱动程序而变化.您只需要信任驱动程序.司机不值得信赖.最重要的是,在您的计算机上执行的不受信任的代码.就像下载随机的.exe并执行它们一样,因此不会发生.

A binary shader is a blob you give to the driver, you have no chance to inspect it or verify its not doing something bad as it's a driver proprietary binary. There is no documentation on what's in it, the format, they can change with every GPU and every driver. You just have to trust the driver. Drivers are not trustworthy. On top of which it's untrusted code executing on your machine. It would no different than downloading random .exes and executing them therefore it won't happen.

对于WebGPU,不,WebGL不再存在安全风险.即使使用二进制格式,该二进制格式也适用于WebGPU本身,而不适用于驱动程序. WebGPU将读取二进制文件,检查是否遵循所有规则,然后生成与用户的GPU匹配的着色器.生成的着色器可以是GLSL,HLSL,MetalSL,SPIR-V,无论如何工作,但与WebGL相似,只有在验证所有规则后,它才会编写一个着色器,然后像WebGL一样,它编写的着色器将包括变通办法,夹紧除此之外,还需要确保着色器安全.请注意,截至今天2018/11/30,尚未确定WebGPU的着色器格式是什么. Google和Mozilla正在推动以二进制形式苹果和微软正在推动WHLSL ,这是HLSL文本的一种变体

As for WebGPU, No, there is no more security risk with WebGL. Even if it uses a binary format that binary format will be for WebGPU itself, not the driver. WebGPU will read the binary, check all the rules are followed, then generate a shader that matches the user's GPU. That generated shader could be GLSL, HLSL, MetalSL, SPIR-V, whatever works but similarly to WebGL it will write a shader only after verifying all the rules are followed and then the shader it writes, just like WebGL, will include workarounds, clamping and whatever else is needed make the shader safe. Note as of today 2018/11/30 it's undecided what the shader format for WebGPU is. Google and Mozilla are pushing for a subset of SPIR-V in binary, Apple and Microsoft are pushing for WHLSL, a variation of HLSL in text

请注意,当浏览器显示"RATS!WebGL这是一个障碍"时,这并不意味着驱动程序崩溃了.相反,它几乎总是意味着GPU重置时间太长.在Chrome(不确定其他浏览器)中,当Chrome要求GPU(通过驱动程序)执行某项操作时,它将启动计时器.如果GPU在2-5秒钟内仍未完成(不确定实际的超时时间),则Chrome将终止GPU进程.这包括编译着色器,并且由于DirectX花费的时间最多,因此这就是DirectX上出现此问题最多的原因.

Note that when the browser says "RATS! WebGL it a snag" that doesn't mean the driver crashed. Rather it nearly always means the GPU was reset for taking too long. In Chrome (not sure about other browsers), when Chrome asks the GPU (via the driver) to do something it starts a timer. If the GPU doesn't finish within 2-5 seconds (not sure the actual timeout) then Chrome will kill the GPU process. This includes compiling shaders and since it's DirectX that takes the most time to compile this is why this issues comes up most on DirectX.

在Windows上,即使Chrome没有执行此操作,Windows也会执行此操作.这主要是因为大多数GPU(也许全部在2018年)无法像CPU一样执行多任务.这意味着,如果您给他们30分钟的工作时间,他们将在不中断的情况下完成30分钟的工作,这基本上会冻结您的计算机,因为您的计算机需要GPU绘制应用程序窗口等.在过去,Windows可以解决此问题,就像Chrome,如果时间过长,请重置GPU.过去,Linux和Mac只能冻结30分钟或使操作系统崩溃,因为该操作系统希望能够绘制图形而不能.在过去8年中的某个时候,Mac和Linux在此方面做得更好.在任何情况下,Chrome都需要尝试主动,因此它会使用自己的计时器并在耗时过长的情况下将其杀死.

On Windows even if Chrome didn't do this Windows does this. This is mostly because most GPUs (maybe all in 2018) can not multitask like a CPU can. That means if you give them 30 minutes of work to do they will do it without interruption for 30 minutes which would basically freeze your machine since your machine needs the GPU to draw application windows etc. In the past Windows got around this by, just like Chrome, resetting the GPU if something took too long. It used to be that Linux and Mac would just freeze for those 30 minutes or crash the OS since the OS would expect to be able to draw graphics and not be able to. Sometime in the last 8 years Mac and Linux got better at this. In any case, Chrome needs to try to be proactive so it uses its own timer and kills things if they are taking too long.

这篇关于WebGL如何避免长着色器编译使选项卡停滞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆