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

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



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: