   Slow DX10 shader loop?
  Hi, in my basic 3D engine ive added the ability to add multiple lights to the scene. My shader contains a loop that applies a new light based on its light ID. All lights are stored within an array. But doing it this way is EXTREMELY slowww! And was wondering what a better option would be?This is what my shader looks like. Take a look in the pixel shader for the light loops.Quote:#include "lighthelper.fx"  #define MAX_LIGHTS 50cbuffer cbPerFrame{float3 gEyePosW;Light gParallelLight[MAX_LIGHTS];Light gPointLight[MAX_LIGHTS];Light gSpotLight[MAX_LIGHTS];Light gLight;intgNumParLights;int gNumPointLights;int gNumSpotLights;};cbuffer cbPerObject{float4x4 gWorld;float4x4 gWVP;};struct VS_IN{float3 posL    : POSITION;float3 normalL : NORMAL;float4 diffuse : DIFFUSE;float4 spec    : SPECULAR;};struct VS_OUT{float4 posH    : SV_POSITION;    float3 posW    : POSITION;    float3 normalW : NORMAL;    float4 diffuse : DIFFUSE;    float4 spec    : SPECULAR;};VS_OUT VS(VS_IN vIn){VS_OUT vOut;// Transform to world space space.vOut.posW    = mul(float4(vIn.posL, 1.0f), gWorld);vOut.normalW = mul(float4(vIn.normalL, 0.0f), gWorld);// Transform to homogeneous clip space.vOut.posH = mul(float4(vIn.posL, 1.0f), gWVP);// Output vertex attributes for interpolation across triangle.vOut.diffuse = vIn.diffuse;vOut.spec    = vIn.spec;return vOut;} float4 PS(VS_OUT pIn) : SV_Target{// Interpolating normal can make it not be of unit length so normalize it.    pIn.normalW = normalize(pIn.normalW);    SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec}; float3 litColor;for(int i = 0; i <gNumParLights;i++){litColor += ParallelLight(v, gParallelLight, gEyePosW);}for(int i = 0; i <gNumPointLights; i++){litColor += PointLight(v, gPointLight, gEyePosW);}for(int i = 0; i <gNumSpotLights; i++){litColor += Spotlight(v, gSpotLight, gEyePosW);}    return float4(litColor, pIn.diffuse.a);}technique10 LightTech{    pass P0    {   SetVertexShader( CompileShader( vs_4_0, VS() ) );   SetGeometryShader( NULL );   SetPixelShader( CompileShader( ps_4_0, PS() ) );    }}So why are loops so slow within a shader or is it something im doing wrong?Thanks!!!   
  Do you have timing results that you could provide here such as the delta between using 1 light vs 50?Were the loops unrolled when it was compiled?  You can check the disassembly to see what happened using fxc.exe   ;  Try to decorate the for loops with the "loop" attribute to hint to the compiler that you want dynamic looping:[loop] for (...) {...}As of now, the compiler probably unrolls the loops by inlining the instructions 50 times within the loop. This is because it doesn't know in advance how many lights you have at runtime. If you actually have close to 50 lights, the inlining is faster than dynamic looping since the looping itself adds some overhead.   ;  Well, I added the [loop] attribute in front of the 3 light loops and it speeds up the application by about 3 frames per second. At the moment i only get  +- 35 FPS. If i use no lights in my scene i get about 200 FPS.-Does the compiler automatically inline  the instructions?-Also, i thought the compiler does know how many lights i have at runtime because the engine first adds up the number of lights and then loops only through them.Quote:for(int i = 0; i <gNumParLights;i++)Would it have something to do with my actual C++ code that is causing it to run so slow?   ;  The compiler tends to unroll loop contents if the loop boundaries are known at compile time, if the upper boundary is a reasonably small value and if the loop contents are reasonably short. The shader/effect compiler cannot assume anything about any constants set during runtime, since the compilation process is totally separated from the loading and running of the shaders.In your case, it could deduce that the maximum number of lights is 50 (per light type), because in the loops you access elements of arrays that have a fixed maximum of 50 elements (though I haven't tried to compile this to test).Light calculations can be slow, especially on pixel shaders. Also, if you use dynamic conditionals in the light functions (as in spotlights), they can break the parallelism of the shader units. Since you haven't shown the contents of "lighthelper.fx", we can't make an assesment about whether this is the case or not.Of course, the host side can be slow too. However, filling 50 light structures is not a huge task for a CPU by itself.You can use PIX to verify the bottleneck location.   ;  Also, remember to compile the effect with full optimizations!   ;  Are you doing forward rendering if so the problem is probably that you are trying to use 50 lights in your scene.   ;  Do you have any tips or ideas how i might stop my loops from unrolling?- Ive tried taking out the loops and filling in the array with literal values and it makes a huge different speed wise. But that wont do because i think i need it to be dynamic. I dont want to have to change anything within the shader when i use the engine.Quote:litColor += ParallelLight(v, gParallelLight[0], gEyePosW);litColor += ParallelLight(v, gParallelLight[1], gEyePosW);;  My apologies, but... 3 lights you get 35 FPS, no lights you get 200 FPS?Ok, there could be be something wrong with the shader (haven't looked at it thoroughly) but please define me your definition of "extremely slow" and your computer specs.Because if with no lights you just get 200 FPS, you either have a small machine or doing something wrong on the CPU side.Also 200 FPS is actually a nice speed for a blank scene for low end GPUs, so, you'll have to tell us your specs. May be you just have a slow machine.Furthermore, GeForce perform loops and dynamic branches veeeeery slow (unless the loop is expanded). ATI is much faster on that one.Also try using the TEXCOORD semantics instead of the DIFFUSE and SPECULAR semantics for vertex shader output, it could help.I don't know what's in lighthelper.fx, but it looks at first glance like you're mixing Goraud shading with Phong. Is the result ok?   ;  I am definately working on a slow machine. The thing is i am working on a laptop, that isnt specifically for gaming. I cant get to my proper PC at the moment because i am away. Im expecting it to be slow and i have considered that this is the problem but it seems a bit extreme that 1 extra light can cause such a speed hit. Or is it?Here are some specs:Acer Aspire 5735Intel Core 2 Duo CPU T5800 @ 2Ghz3GB DDR2 ramIntel onboard graphics(Up to 1244MB)<-Most likely the issue, but still...   