[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] some samples and a question about looping



I meant if there was any difference in the WebGL spec. Probably most
common use of variable length loops would be loops that are simply
bounded by uniforms. I guess memory access can cause problems for
efficiency even then. Perhaps WebGL wiki should have a page with
information about how to best write loops for different platforms, and
other GLSL issues such as floating point precision.

-- Sami

On Tue, Dec 28, 2010 at 10:48 PM, Steve Baker <steve@sjbaker.org> wrote:
> It's not the case that vertex shaders and fragment shaders work the same
> way - at least not on all hardware.  Firstly, there are graphics chips
> that don't have vertex shader hardware at all - and run your vertex
> shaders in the CPU.  But even on decent graphics cards, the vertex
> shader processors may be very different beasts than the fragment shaders.
>
> By the very nature of fragment shading, there have to be a LOT of
> separate processors running in parallel - and they have to run their
> code in perfect lock-step.  That is so that they can be super-efficient
> SIMD machines - but also so that things like texture fetching, MIPmap
> level calculations and ddx/ddy instructions can work efficiently.
>
> So when you're looping - even if the loop isn't unwound - all of the
> processors may have to execute all of the instructions.  For loops with
> variable end-conditions, this poses nasty little problems for the chip
> designer...hence low-end hardware doesn't do it for the fragment
> shader.   Vertex shaders don't really have that problem.  Firstly, there
> are far fewer vert shader processors than frag shaders - secondly, they
> don't have to support MIPmapping, ddx/ddy, etc.  (One reason why vertex
> textures don't support MIPmapping).
>
> The consequence of this is that if your loop has a large number for it's
> termination condition - but you believe that it's very rare to need to
> go through the entire loop every time - you may be horrified to discover
> that the entire loop always takes as much time as it would take to run
> to completion - even though you are doing "break" in the middle of it!!
>
> Hence, algorithms that need long, variable termination-condition loops
> are often poor candidates for implementation on the GPU.
>
>  -- Steve
>
> On 12/27/2010 08:13 AM, Sami Mäkelä wrote:
>> I wasn't claiming that WebGL unfolds the loop. Also variables can be
>> used to terminate loops (with "break"), they just cannot be used in
>> the condition of the "for" loops. It is my understanding that vertex
>> and fragment shaders have same control flow (except "discard"),
>> perhaps I'm missing something? Anyway the issue is that if arbitrary
>> conditions were allowed in the for-loop, I could make a shader that
>> won't be unfolded by ATI GL driver. Therefore, the restriction in the
>> spec has actually forced my program to be less portable than it should
>> have been.
>>
>> My shader works fine in Nvidia GL (Win7 and Linux), ANGLE with ATI,
>> Nvidia and Intel (some unfolding or at least "optimization" seems to
>> happen in DirectX), so perhaps it works in mobile devices too, at
>> least with smaller framebuffer size (unless the drivers in mobile
>> devices try to unroll the loop beyond their resources). On the other
>> hand, because "long loops" are undefined by the GLSL ES spec, any
>> shader that uses loops is not required to work on mobile or other
>> devices.
>>
>> -- Sami
>>
>> On Mon, Dec 27, 2010 at 5:17 AM, Mark Callow <callow_mark@hicorp.co.jp> wrote:
>>
>>> I do not think that WebGL is unrolling your loop.  I think it is entirely to
>>> do with the ATI drivers. WebGL does not require unrolling, it merely states
>>> that variables cannot be used to terminate loops in fragment shaders.
>>>
>>> If your unrolled loop is taking gigabytes of memory, I would worry about its
>>> performance when not unrolled, especially on mobile devices.
>>>
>>> Regards
>>>
>>> -Mark
>>>
>>>
>>>
>>> On 27/12/2010 01:13, Sami Mäkelä wrote:
>>>
>>> Ok, it seems to me that on platforms where infinite or otherwise too
>>> long loops in the shader can crash the system,  unrolling should be
>>> forced, or at least the driver should be made check that no such loops
>>> are possible. Hopefully that is already the case in current WebGL
>>> implementations.
>>>
>>> Anyway, as you pointed out, the restriction in WebGL (Appendix A.4 in
>>> GLSL ES 1.0 spec) doesn't exclude infinite or too long loops (and also
>>> while-loops can be unrolled by drivers if they have constant number of
>>> iterations). Just like WebGL doesn't enforce other minimum
>>> requirements of ES (for example VTF is allowed), it should not enforce
>>> this one. In fact, this restriction doesn't prevent any unportable
>>> programs, because the loop bound can be selected high enough so that
>>> it won't work on platforms that unroll it. Actually the restriction
>>> can make programs even less portable (for example my Xmas star doesn't
>>> seem to work on ATI GL drivers for Windows 7, it just allocates
>>> gigabytes of memory). I think that the only way to make loops portable
>>> is testing on different platforms, this restriction isn't helping at
>>> all...
>>>
>>> -- Sami
>>>
>>> On Sat, Dec 25, 2010 at 3:26 PM, Steve Baker <steve@sjbaker.org> wrote:
>>>
>>> The WebGL spec requires that GLSL implementations limit themselves to
>>> the MINIMUM OpenGLES2.0 requirements - so we don't allow loops with a
>>> non-constant number of iterations (and we specifically disallow those
>>> where the value of a uniform is used to determine the termination
>>> condition).
>>>
>>> In other words, only loops that could (in principle) be unrolled at
>>> compile time are allowed.
>>>
>>> I believe that there are two reasons for this - one is that a lot of
>>> hardware doesn't support loops at all - so the compiler is forced to
>>> unroll them.  The other is as a kind of security measure to make sure
>>> the bad guy can't lock up your computer by putting a shader into an
>>> infinite loop.
>>>
>>> Now - I agree that there is an issue here...while it's reasonable to
>>> require loops that could in principle be unrolled - should WebGL force
>>> them to actually be unrolled in practice?   Arguably, it shouldn't
>>> because that makes the shader code much longer than it needs to be on
>>> machines that CAN support looping at the hardware level.
>>>
>>> I say "arguably" because the current restrictions don't seem to prevent
>>> you from saying something like:
>>>
>>>     for ( float i = 100000000 ; i < 100000001 ; i += 0.1 )
>>>       dosomething ;
>>>
>>> ...which is legal (per the specification) - and on paper, only iterates
>>> 10 times.   But in practice, it would probably loop forever because math
>>> precision isn't good enough and 100000000+0.1 evaluates to 100000000, so
>>> the loop never reaches its target.  If loops are not literally unrolled
>>> by the compiler, this kind of infinite looping would be hard to
>>> definitively exclude.
>>>
>>> You might imagine that the shader verifier could try unrolling the loop
>>> to make sure it's possible - and if that works, pass on the original
>>> rolled-up loop to the underlying GLSL compiler - but that's awfully
>>> risky if you don't know the precise inner workings of the GPU's floating
>>> point math unit.  The bad guy might easily find a 'chink' in that armor
>>> with carefully-chosen data.
>>>
>>> Your work-around of looping a very large number of times and then
>>> breaking out in the middle is legal in principle - but if the compiler
>>> does unroll loops, you'll run out of shader instructions and it won't
>>> compile.
>>>
>>>  -- Steve
>>>
>>>
>>> On 12/24/2010 10:51 AM, Sami Mäkelä wrote:
>>>
>>> Hello!
>>>
>>> I've updated my samples at http://programming-progress.com/webgl.html
>>> so that they now work (or do not work) as expected on the latest
>>> browsers. At least check out the Xmas star.
>>>
>>> One question: It seems like the ATI GL drivers on at least Windows 7
>>> 64bit seem to always unfold loops that have constant number of
>>> iterations. My workaround was to force the looping to be unknown (by
>>> using uniforms). This doesn't work anymore because ANGLE validator
>>> doesn't accept it. Is there some example on any platform where
>>> converting the shader code to the form accepted by ANGLE would
>>> actually convert a non-working shader to a shader that works with the
>>> driver?
>>> Anyway even if there is some driver that cannot handle full looping,
>>> it should not matter, because any program can be converted into the
>>> form accepted by ANGLE for example using
>>> while (cond) body; ===> for (int i = 0; i < INFINITY-1; i++) { if
>>> (!(cond)) break; else body; }
>>> As summary, this check might cause some shaders to become impossible
>>> on some environments, and it does not add to compatibility, because
>>> the shaders could be easily converted into form that should be
>>> accepted, if the original code is rejected by the driver. Wouldn't it
>>> just be better to drop this check and say that the loops are "too
>>> long" (and hence undefined) if they are not supported by the driver?
>>>
>>> -- Sami
>>> -----------------------------------------------------------
>>> You are currently subscribed to public_webgl@khronos.org.
>>> To unsubscribe, send an email to majordomo@khronos.org with
>>> the following command in the body of your email:
>>>
>>>
>>>
>>> -----------------------------------------------------------
>>> You are currently subscribed to public_webgl@khronos.org.
>>> To unsubscribe, send an email to majordomo@khronos.org with
>>> the following command in the body of your email:
>>>
>>>
>> -----------------------------------------------------------
>> You are currently subscribed to public_webgl@khronos.org.
>> To unsubscribe, send an email to majordomo@khronos.org with
>> the following command in the body of your email:
>>
>>
>
>

-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email: