HLSL - problem with while statement

Started by
4 comments, last by EvilDecl81 18 years, 4 months ago
Hello! I use HLSL for a volume rendering algorithm (shader 3, geforce 6800 ultra used). Now I have some problem with the while-statement, i.e. the following code would not work: while(vActVolPos.x < 0.3f) { vActVolPos.x = vActVolPos.x + 0.05; } nevertheless - this works fine: int i = 0; int j = 10; while(i < j) { i++; } So it looks like it is a float specific problem... but in the DX SDK documentation there are samples like: while ( color.a > 0.33f ) { color /= 2; } so, I think it should work... any ideas what can be the problem? Brisco
Advertisement
I tried a few things and it seems that it is not possible to use variable conditions like x < y if not at least one of them is constant (that means, i.e. int y = 10 is defined before the loop). Is this true?
Quote:Original post by Brisco
I tried a few things and it seems that it is not possible to use variable conditions like x < y if not at least one of them is constant (that means, i.e. int y = 10 is defined before the loop). Is this true?

Unfortunately, I don't have an SM3.0 card to play around with right now but you can check this pretty easily in your original while loop:
const float fZeroPointThree = 0.3f;while(vActVolPos.x < fZeroPointThree ){  vActVolPos.x = vActVolPos.x + 0.05;}


neneboricua
sorry for the long delay... your code example would work, because the compiler can insert 0.3f at compilation time.

But I figured out something interesting:

for (int i=0; i < n; i++)
{
//do something
}

When I load an effect file with this code into the DirectX Viewer application (which is delivered with the latest DXSDK), I get an error X3511: loop does not appear to terminate in a timely manner (1024 iterations)

Nevertheless - n will never be greater than 100 - so I really don't understand the restriction. Seems like the only solution to this problem is something like this:

for (int i=0; i < 100; i++)
{
if(i < n)
{
//do something
}
}

but this is not really useful because it would massivly affect performance.

Brisco
It very much depends on how the terminating condition of the loop is defined and on what shader version you're targeting.

If your upper bound on the loop iteration is a constant that can be determined at compile time, you should have no trouble at all. If it is a constant determined by the application in the vein of the number of lights to run through, then you should pass this value as a parameter to the technique. The shader compiler will essentially unroll the loop. The BasicHLSL sample does this.

If the upper bound is set as a regular constant by the application and cannot be determined at shader compile time, dynamic branching must be supported for it to work. Finally, if the upper bound is determined on a pixel-by-pixel basis from within the pixel shader itself, then this will definately require at least dynamic branching. I'm not sure if even an SM3.0 card could handle this situation, though since I don't have one to mess around with, I can't be totally sure.

neneboricua
Quote:Original post by Brisco
sorry for the long delay... your code example would work, because the compiler can insert 0.3f at compilation time.

But I figured out something interesting:

for (int i=0; i < n; i++)
{
//do something
}

When I load an effect file with this code into the DirectX Viewer application (which is delivered with the latest DXSDK), I get an error X3511: loop does not appear to terminate in a timely manner (1024 iterations)

Nevertheless - n will never be greater than 100 - so I really don't understand the restriction. Seems like the only solution to this problem is something like this:

for (int i=0; i < 100; i++)
{
if(i < n)
{
//do something
}
}

but this is not really useful because it would massivly affect performance.

Brisco



Is this a pixel shader or a vertex shader? HLSL does alot of code analysis to see if a loop will terminate or not - so what can happen is if you have a loop that needs to unroll for whatever reason (without seeing your code, I can't really make a judement call here) then it has to unroll, which it can't do if the loop goes on forever.

Unfortantly, especially for pixel shader targets, there are very few cases where you can actually use a loop to do anything useful, most of the time the time HLSL has to unroll it. Addtionally, for while loops, in order for HLSL to emit correctly it has to know the maximum iteration count on the loop because this is implemented via an rep instruction with aliteral loop count max if 256. Thus, HLSL can't actually emit correct code if it has no way of knowing what the max count of a loop iteration can be. I imagine this latter thing is your problem.

You can bind the loop count if you want by doing something like

int i =0;

while(vActVolPos.x < .3 && i < 100)
{
...
i++;
}
EvilDecl81

This topic is closed to new replies.

Advertisement