WebGL how to avoid long shader compile stalling a tab

可紊 提交于 2019-12-05 19:46:51

There is no good solution.

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 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. They aren't portable

    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.

  2. It would be a huge security issue.

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

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.

Here's a thread from 2 years ago 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.


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.

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.

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

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.

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!