Re: CSS shaders DoSing the browser?

On Feb 29, 2012, at 6:56 PM, Gregg Tavares (勤) wrote:

> As you're probably aware, it's possible to effectively lock up certain machines by giving the GPU something that takes a long time to do.
> 
> Windows gets around this problem by resetting the GPU after a couple of seconds if it becomes unresponsive.
> Newer Linux GL drivers support the GL_ARB_robustness extension that provides a similar feature to Windows.
> In the future GPUs will be preemptive.
> 
> In particular though, XP machines, OSX, iOS and Android as far as I know all basically freeze under these conditions. I've kind of assumed that's why Apple has not shipped WebGL in Safari or nor enabled it for regular pages on iOS yet. (Yes, I know I'm assuming that's the reason though I have no actual word from Apple)
> 
> Anyway, CSS shaders have this same problem and I'm not sure if people are aware of the issue.
> 
> I think most people believe you need complex shaders to DoS the GPU. In fact you need no shaders. You can DoS even a fixed function GPU just by giving it lots of very large polygons to draw.
> 
> As an example here's a sample that demonstrates the issue
> 
> https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/extra/lots-of-polys-shader-example.html
> 
> The sample draws one subdivided plane. This is analogous to using the vertexMesh attribute in CSS shaders. The vertex shader then, knowing the resolution of the mesh, expands each sub-quad to the full size of rendering surface. The fragment shader is minimal effectively the same that would be used for CSS shaders with no extra effects applied.
> 
> In this particular case I set the subdivision to 1000 which is equivalent to vertexMesh: 1000, 1000 but I believe even a setting of 100x100 would be enough to DoS many slower GPUs.
> 
> There may be work arounds, you can limit each draw call to only 100 polygons for example and that might solve the problem. On the other hand that might be fairly limiting in terms of speed for more interesting effects. For example if you used a monospace font you should be able to do something like this with CSS shaders
> 
> http://www.html5rocks.com/en/tutorials/webgl/million_letters/million_letters.html
> 
> But that only runs smoothly if it's 1 draw call. Splitting it into one draw call for every 100 sub-quads on the off chance that the shader might draw every quad really large would likely kill perf for shaders that don't. 
> 
> Has this been considered?

Apple has not shipped WebGL because OpenGL drivers, on all platforms, are generally insecure. This is fine for games where the developer is trying hard to avoid crashes and GPU resets. If a game crashes your machine or behaves badly, you need only look at the box and see if your graphics card is supported. If not, you either don't run the game or you go get a better card. 

That's not possible on the web. Not only does something reasonable have to happen on every browser on every platform, but the browser must protect itself against malicious content. Some drivers today will cleanly do a GPU reset when a misbehaving shader is executed. But that is not good enough for OSX drivers. In all cases I know of, GPU reset affects all running OpenGL apps. On Windows this is dealt with by issuing a "context lost" message to every app, and it's the responsibility of each app to reinitialize it's context before continuing. And even there I've heard stories of apps that don't do a particularly good job of restoring state. On OSX there is no such message OpenGL apps have to deal with today. So a GPU reset can't have "innocent victims" on OSX. But some drivers have very poor behavior when attempting to do a GPU reset. They will hang or ever kernel panic the system. All of these things need to be fixed before Apple can consider WebGL ready for prime time.

But even when these issues are dealt with and drivers are more reliable, the user experience will be less than ideal. Today's GPUs can work on one thing at a time. If a shader takes 2 seconds before the system decides it should be kicked out, that means no other graphics operations can be processed during this time. Since modern OS's use the GPU for system level rendering, a poorly behaving shader will cause visual glitches and poor performance throughout the system.

What we really need in the graphics subsystem is the ability to have the GPU multitask like modern CPU's do. If a shader context can be stopped, and swapped out for other system operations, then there would be no need for GPU reset. The browser would simply have to decide how much time a rendering operation should be allowed to run and then terminate it when it is taking too long. I've been assured such GPU hardware is on the horizon, but so far I haven't seen any. Until then, the best we can do on any platform is to try to handle GPU reset as gracefully as possible and hope for the best.

-----
~Chris
cmarrin@apple.com

Received on Thursday, 1 March 2012 16:54:44 UTC