Update
铬添加了KHR_parallel_shader_compile https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/扩展允许您查询着色器是否完成编译。
不幸的是,截至 2021 年 1 月,只有 Chromium(Chrome/Edge/Brave/等...)实现了它
原答案
没有好的解决办法。
Windows 上的浏览器使用 DirectX,因为许多计算机默认情况下不提供 OpenGL,而且浏览器所需的许多其他功能与 OpenGL 不兼容。
DirectX 需要很长时间来编译着色器。只有微软可以解决这个问题。 Microsoft 已提供 HLSL 着色器编译器的源代码,但它仅适用于 DX12。
有些人建议允许网页提供二进制着色器,但这永远不会发生,原因有两个
-
它们不便于携带
网页必须提供数百或数千种二进制着色器变体。适用于每种类型的 GPU * 每种类型的驱动程序 * 每个平台(iOS、Android、PI、Mac、Windows、Linux、Fire...)。网页应该在任何地方加载,因此着色器二进制文件不是网络的解决方案。
-
这将是一个巨大的安全问题。
Having users download random binary blobs that are given to the OS/GPU to execute would be huge source for exploits.1
请注意,某些浏览器(特别是 Chrome)会在幕后本地缓存着色器二进制文件,但这对首次编译没有帮助。
所以目前基本上没有解决办法。您可以制作更简单的着色器或一次编译更少的着色器。人们要求使用异步扩展来编译着色器,但没有任何进展。
这是2年前的帖子https://www.khronos.org/webgl/public-mailing-list/public_webgl/1702/msg00039.php https://www.khronos.org/webgl/public-mailing-list/public_webgl/1702/msg00039.php
只是个人意见,但我猜测异步扩展没有太多变化的原因是它的实现工作比听起来要多,并且存在大量具有复杂着色器的网站并且似乎可以工作。
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 并执行它们没有什么不同,因此不会发生这种情况。
至于WebGPU,不,WebGL 不再有安全风险。即使它使用二进制格式,该二进制格式也适用于 WebGPU 本身,而不是驱动程序。 WebGPU 将读取二进制文件,检查是否遵循所有规则,然后生成与用户 GPU 匹配的着色器。生成的着色器可以是 GLSL、HLSL、MetalSL、SPIR-V,无论什么都可以,但与 WebGL 类似,只有在验证所有规则都遵循后,它才会编写着色器,然后它编写的着色器,就像 WebGL 一样,将包括解决方法、钳位以及任何其他需要使着色器安全的事情。请注意,截至今天 2018 年 11 月 30 日,WebGPU 的着色器格式尚未确定。 Google 和 Mozilla 正在推动 SPIR-V 的二进制子集,苹果和微软正在推动 WHLSL https://webkit.org/blog/8482/web-high-level-shading-language/,HLSL 的文本变体
请注意,当浏览器显示“RATS!WebGL it a snag”时,并不意味着驱动程序崩溃了。相反,它几乎总是意味着 GPU 由于花费太长时间而被重置。在 Chrome 中(不确定其他浏览器),当 Chrome 要求 GPU(通过驱动程序)执行某些操作时,它会启动一个计时器。如果 GPU 在 2-5 秒内没有完成(不确定实际超时),那么 Chrome 将终止 GPU 进程。这包括编译着色器,并且由于 DirectX 需要最多的时间来编译,这就是这个问题在 DirectX 上出现最多的原因。
在 Windows 上,即使 Chrome 不这样做,Windows 也会这样做。这主要是因为大多数 GPU(可能全部在 2018 年)无法像 CPU 那样进行多任务处理。这意味着如果你给他们 30 分钟的工作时间,他们会在 30 分钟内不间断地完成工作,这基本上会冻结你的机器,因为你的机器需要 GPU 来绘制应用程序窗口等。在过去,Windows 通过以下方式解决了这个问题: Chrome,如果某件事花费太长时间,则重置 GPU。过去,Linux 和 Mac 只会在这 30 分钟内冻结或使操作系统崩溃,因为操作系统希望能够绘制图形,但实际上却无法。在过去 8 年中的某个时候,Mac 和 Linux 在这方面做得更好。无论如何,Chrome 需要尝试主动行动,因此它会使用自己的计时器,并在时间过长的情况下杀死它们。