[Public WebGL] Infinite loops allowed in WebGL 1.0 currently?

Kenneth Russell [email protected]
Mon Mar 9 14:35:54 PDT 2015

On Mon, Mar 9, 2015 at 1:01 PM, Ben Constable <[email protected]> wrote:
> The problem with not unrolling is that not all hardware is able to do this. D3D10 era hardware can have loops encoded in the ISA but I believe that there are D3D9 era parts that cannot do this and a lot of current mobile hardware has inherited this limitation. We don't unconditionally unroll things right now, but sometimes the HLSL compiler decides it wants to unroll things even though I did not tell it to, and then it runs into the same problems that I have.
> At the end of the day, we have a good quantity of hardware out there that cannot do dynamic loops at all. The fact that a rich language like GLSL allows you to encode dynamic loops in so many creative ways just means we need to have a tighter specification for controlling against them.
> It is conceivable that we can have different behavior depending on the hardware class. The only reason I hesitate a little around that is that the testing matrix for both myself and my customers becomes more complicated every time I do that :) Now, this problem already exists to some extent (somebody writing a big shader and it won't run on mobile) but limiting the damage of this problem for folks building stuff on the web should always be a goal.
> When I see validation for loops like the example here I see the halting problem in not very good disguise :) The input to the program can very easily make it impossible to determine if a loop terminates. For example, somebody could preprocess the geometry and textures to ensure that their shader always terminates their while(true) loops, but there is no way for a compiler to distinguish this. I see our static analysis software we use internally struggle with stuff like this all of the time and people end up using pragmas or more complicated histrionics to solve the issue.
> Right now I see some options:
> a) We can go ahead and reject code like the below on certain classes of hardware with a compile error, and permit it on most hardware with some combination of attributes on the loops. I think this is ultimately more friendly developers. Does "platform dependent" not cover the case where we suspect the loop is problematic and reject compilation?
> b) We can harden the specification somewhat for loops to avoid allowing them to resemble while(true). With shader code this actually adds value because it forces closer examination of what is actually desired. I don't have huge high hopes for this given that we have stuff in the wild relying on it, but I can always have some hope :)

On the whole I would lean toward option (a). As far as I can tell from
reading the GLSL ES 3.00.4 specification, the restrictions on loop
structure have been lifted compared to version 1.0.17. This means that
ES 3.0 / WebGL 2.0 will implicitly solve this problem by only running
on hardware that supports dynamic loops.

Since supporting this feature is the clear direction both for mobile
hardware and WebGL, I'd rather leave this corner case as is rather
than trying to mandate that such loops must fail shader compilation.
As you anticipate, specifying this is bound to have serious
ramifications both for the WebGL 1.0 spec and existing shaders. I'm
sure we will get it wrong both in the spec and tests the first time
around, and that ultimately an airtight specification of admissible
loops is impossible.

Option (a) is perfectly legal according to the existing specs, since
shaders can fail to compile for any platform-dependent reason --
though it's unfortunate, as it leaves unportable behavior in the
shader spec. We should also encourage authors to restructure their
shaders to avoid problems like this on a case-by-case basis.

Is this a satisfactory solution for you?

> On another fork I saw Jamie mention a desire to do some kind of an amend here.

Right; I think this was
https://code.google.com/p/angleproject/issues/detail?id=901 , which is
blocking the integration of drawElements' AOSP tests in ANGLE. I'm not
sure but think it's likely these tests will only pass on hardware that
supports dynamic loops and that doesn't require loops to be unrolled.


> -----Original Message-----
> From: Kenneth Russell [mailto:[email protected]]
> Sent: Friday, March 6, 2015 5:14 PM
> To: Ben Constable
> Cc: public webgl
> Subject: Re: [Public WebGL] Infinite loops allowed in WebGL 1.0 currently?
> On Fri, Mar 6, 2015 at 1:04 PM, Ben Constable <[email protected]> wrote:
>> We were looking at a bug in IE recently and came across an interesting case:
>> http://threejs.org/examples/#webgl_materials_parallaxmap
>> This has this fragment of GLSL code:
>>                                "for ( int i = 0; i == 0; i += 0 ) {",
>> This is obviously an infinite loop. I am assuming that the site is
>> working because the code is never hit in practice.
>> The way that we translate GLSL, this is a bit tricky for us. It
>> appears that ANGLE is outputting [loop] in HLSL, and on most hardware
>> this will happily generate an infinite loop that causes TDRs in the
>> shader (we can make Chrome TDR using loop constructs like this).
>> The specification for loops in GLSL seems to have a lot of effort put
>> into preventing unverifiable loops – is the case of a zero increment
>> an oversight in the specification? I would love to return an error for
>> this kind of case but if I do that now, I will end up not working on a
>> site that works in ANGLE based browsers, and this is not good for interoperability.
> It looks like the shader more precisely does
>   for ( int i = 0; i == 0; i += 0 ) {
>     if ( heightFromTexture <= currentLayerHeight ) {
>       break;
>     }
>     currentLayerHeight += layerHeight;
>     // ...
>   }
> GLSL ES 1.0.17 appendix A allows for_headers including the form:
>   loop_index += constant_expression
> and section 6.3 "Iteration" says
>   Non-terminating loops are allowed. The consequences of very long or non-terminating loops are platform dependent.
> so strictly speaking, the shader should validate.
> There are surely many shaders using conditional breaks to work around the lack of dynamic upper bounds in loop conditions. I'm pretty sure I've seen similar shaders using constructs like
>   while (true) {
>     if (something)
>       break;
>     // ...
>   }
> It would be ideal if we could figure out a solution allowing your GLSL translator to run these shaders. If the issue is that you unconditionally unroll loops, can you avoid doing so only in these problematic situations?
> -Ken

You are currently subscribed to [email protected]
To unsubscribe, send an email to [email protected] with
the following command in the body of your email:
unsubscribe public_webgl

More information about the public_webgl mailing list