unrolling for loop

Posted By: txesmi

unrolling for loop - 07/26/15 12:49

Hi,
I have written a small shader that contains a for loop to sample an image by rows but I am getting an unrolling error that is breaking my nuts.

Here is the shader:
Code:
float4 vecSkill1;

texture mtlSkin1;
sampler texSampler = sampler_state { Texture = <mtlSkin1>; Mipfilter = Point; Minfilter = Point; Magfilter = Point; AddressU = Wrap; AddressV = Wrap; };

float4 PS ( in float2 inTex: TEXCOORD0 ) : COLOR0
{
	inTex.xy *= vecSkill1.xy;
	float4 color1 = 0;
	int layerCount = vecSkill1.z;
	for ( int layer=0; layer<layerCount; layer+=1 )
	{
		float4 color2 = tex2D ( texSampler, inTex.xy );
		color1.rgb = lerp ( color1.rgb, color2.rgb, color2.a );
		color1.a = max ( color1.a, color2.a );
		inTex.y += vecSkill1.w;
	}
	return color1;
}



I set the material skills as follows:
Code:
mtlRenderer->skill1 = floatd ( bmap_width(bmp), bmap_width(bmpRenderer) ); // width proportion between render target (bmp) and color sampler (bmpRenderer)
mtlRenderer->skill2 = floatd ( bmap_height(bmp), bmap_height(bmpRenderer) ); // height proportion between render target (bmp) and color sampler (bmpRenderer)
mtlRenderer->skill3 = floatv ( 2 ); // number of loops 
mtlRenderer->skill4 = floatd ( 1, bmap_height(bmpRenderer) / bmap_height(bmp) ); // height of render target inside color sampler 0<>1 height range
mtlRenderer->skin1 = bmpRenderer;
bmap_process ( bmp, NULL, mtlRenderer );



And the error:


I checked layerCount and contains the correct value. How the hell can the for loop be unable to unroll? I am totally lost. Any idea would be appreciated.

Salud!
Posted By: Superku

Re: unrolling for loop - 07/26/15 13:52

Loops in shaders are not the same loops as in regular programming languages.
Let's say you write:
for(i = 0; i < 5; i++)
{
value += i;
Color += tex2D(...,i*0.25);
}
into your code, then the compiler will unroll the for loop statement to something like
value += 0;
Color += tex2D(...,0*0.25);
value += 1;
Color += tex2D(...,1*0.25);
value += 2;
Color += tex2D(...,2*0.25);
value += 3;
Color += tex2D(...,3*0.25);
value += 4;
Color += tex2D(...,4*0.25);

As a result, shaders don't like dynamic for loop ranges that much. You can try one of 2 approaches (that I am aware of/ I use):

for ( int layer=0; layer<8; layer+=1 )
{
if(layer < layerCount) {...}
}

or

for ( int layer=0; layer<8; layer+=1 )
{
multiply with another value, let's say
float array_active_var[8];
which is non-zero if used
}

The first way should be faster but if loops are special in shader language too and are not as fast as in regular programming.

Salud!
Posted By: txesmi

Re: unrolling for loop - 07/26/15 17:31

Thank you Superku,
I ultimately decided to build a material for each layer count and forget about dynamic loops.

By the way I tryed to add an integer to the material through SetInt DX function. It fails in the compilation too. I am pretty confused because iLights or iWeights are also integers containing dynamic ranges and are commonly used into for loops with no troubles.

i força al canut wink
Posted By: Hummel

Re: unrolling for loop - 07/26/15 21:27

Shader Model 3 and lower has no native support for integer formats. If you use integers, they will be emulated using lots of floating point arithmetic, which is slow. Just don't do it.
Posted By: txesmi

Re: unrolling for loop - 07/28/15 05:19

Thank you Hummel, valuable info. laugh
© 2024 lite-C Forums