   HLSL Optimization !
  HiI wrote a shader with RenderMonkey, its PS_3, but i want to use it on PS_2 hardwares.Its some days that im trying to optimize it for PS_2, but im not success.Maybe my experience is low ;)However i asked here, to maybe one expert HLSL hero help me.float4 lightColor1;float4 view_position;float ambient;float sideSize;float hdrValue;float4 lightPos;float4 worldOrigin;float lightAttenuation;sampler DecalTex;sampler NormalMapTex;sampler StreetLightsTex;sampler ColorsTex;float4 Light_Point(float4 pos,float4 lightPos,float3 Normal, float3 HalfVect, float4 LightDir,float4 LightColor){float SpecularAttn =pow( saturate(dot(Normal, HalfVect)),64);float DiffuseAttn = saturate(dot(Normal, LightDir));float Dist = length(lightPos - pos);float lightPower =1/((Dist/100)+1);if (lightPower&lt;1)   lightPower=pow(lightPower,lightAttenuation);float4 finalColor=float4(0,0,0,0);if (lightPower&gt;0.005) finalColor=hdrValue*lightPower*LightColor * (SpecularAttn+DiffuseAttn); return finalColor;}float3 lookup(float3 pos,float3 mappos, float3 offsetpos, float3 norm){   float3 c=float3(0,0,0);   float2 coordinate=offsetpos.xz+mappos.xz;   float4 streetlightPos = tex2D( StreetLightsTex, coordinate ); if (streetlightPos.w&gt;0)   { float3 lightvec = streetlightPos - pos; float dist = length(lightvec); lightvec=normalize(lightvec); float circleRadius=1.0; float3 gridLightColor=tex1D(ColorsTex,streetlightPos.w).xyz; if (dist&lt;circleRadius)c=gridLightColor*(circleRadius-dist)/circleRadius*hdrValue;    }    return c;}float4 ps_main(float2 inTxr:TEXCOORD0,float4 LightDir:TEXCOORD1,float3 HalfVect:TEXCOORD2,float4 Pos:TEXCOORD3) : COLOR{float3 normal = tex2D(NormalMapTex,inTxr) * 2 - 1;float4 localPos=(Pos-worldOrigin);float4 mappos=0.5+localPos/(2*sideSize);float gridstep=1.0/16.0;float3 norm=normal;float3 posAsColour=mappos;float3 gridlights =    lookup(localPos.xyz,posAsColour, float3(0,0,0),norm)+   lookup(localPos.xyz,posAsColour, float3(0,0,gridstep),norm)+   lookup(localPos.xyz,posAsColour, float3(0,0,-gridstep),norm)+   lookup(localPos.xyz,posAsColour, float3(gridstep,0,0),norm)+   lookup(localPos.xyz,posAsColour, float3(gridstep,0,gridstep),norm)+   lookup(localPos.xyz,posAsColour, float3(gridstep,0,-gridstep),norm)+   lookup(localPos.xyz,posAsColour, float3(-gridstep,0,0),norm)+   lookup(localPos.xyz,posAsColour, float3(-gridstep,0,gridstep),norm)+   lookup(localPos.xyz,posAsColour, float3(-gridstep,0,-gridstep),norm);return tex2D(DecalTex,inTxr)*(ambient+Light_Point(Pos,lightPos,normal,HalfVect,LightDir,lightColor1)+float4(gridlights.xyz,1));}Note: The shader will simulate street lights on materialThanks for any help.H.AhmadiEDIT: Please use 'source' tags to make your code more readable. Thanks![Edited by - jollyjeffers on April 25, 2009 6:16:57 AM]
  So what's your actual problem? Can you not get it to compile under ps_2_0, or is it just too slow? In the former case, is it a particular expression it doesn't like or is it just a length issue?Your main shader looks ripe for a multi-pass implementation. The gridlights variable is a straight summation and then its just added to the rest of the lighting contributions. Perfect to be split up into multiple passes with additive blending. You've got 9 samples, so maybe refactor it into 1 pass for the main lighting equation and then 3 passes doing 3 of the spot lights each?hthJack   ;Quote:Original post by jollyjeffersSo what's your actual problem? Can you not get it to compile under ps_2_0, or is it just too slow? In the former case, is it a particular expression it doesn't like or is it just a length issue?The main problem is that the shader is slow, and reduce my FPS by factor of 6;The other problem(also is relative to the first problem) is that i have no idea about speeduping the shader, For example HLSL have "Clamp" function , that is very usefull when we want ensure that a value is between "start" and "end" value, but im not success to found any replacement functions for my shader codes (i think some HLSL functions have prebuild circuit on GPU and can speedup the shader comparing with pure codes)!When im rendering a mesh, i must apply my streetlights lighting on it.Im passing my street lights position as a texture(Sampler) to the shader, but with a special hashing(i mean that the pos of lights are near that texture coordinate and the RGBs of the texture are real lights position). then i must search all pixels around of current texture coordinate(that is current pixel position).Calling 9 times "lookup" function take GPU time ! and the main problem is here, i must found a replacement idea for it. or i found a simple "lookup" function.As you said before i must clearly say what i need, but really i have 2 problems that i need help about them:1)Is it any prebuild function in HLSL that be a good replacement of my shader codes, specially for "lookup" function?  Note: i think(but maybe i'm essentialy in wrong) if i reduce my shader lines, then my performance will increase.2)I think Kojack idea about streetlights need a few changes to give better performance.Note:"Kojack idea" is that " we pass lights position as a texture with special hashing, because we need to compute 9 times lighting that maybe don't appear on mesh or is better if i say polygon)".In last, i must mention a thing about PS_2 or PS_3 ,i just interested to know what must we do if we want to run a HLSL shader with limitation of PS_2 ? for example a shader with 200 lines, that you answered me, we call split the shader in multipass, Thanks.Thank you for your attention  Best RegardsH.Ahmadi   ;  You need to start by measuring the speed of the shader with most of the tex2d calls removed.  It needs to be simulated well enough the the compiler becomes unable to optimize the math that relies on the result.  I.e. read from global shader contants.I count 20 texture fetches, this will even stress a lot of SM3 boards (the mid range and low end ones), not to mention anything older.  Fetching a texture and not using it for most or all pixels is about one of the worst things a shader can do, as it represents wasted effort.  I imagine that any given pixel is only really being affecetd by a handful of those lights.;Quote:Original post by ZonerYou need to start by measuring the speed of the shader with most of the tex2d calls removed.  It needs to be simulated well enough the the compiler becomes unable to optimize the math that relies on the result.  I.e. read from global shader contants.I count 20 texture fetches, this will even stress a lot of SM3 boards (the mid range and low end ones), not to mention anything older.  Fetching a texture and not using it for most or all pixels is about one of the worst things a shader can do, as it represents wasted effort.  I imagine that any given pixel is only really being affecetd by a handful of those lights.If i change line 3 of "lookup" function to following line://float4 streetlightPos = tex2D( StreetLightsTex, coordinate ); float4 streetlightPos = float4(0,0,0,0);Then my FPS will increase by factor of 4~5 times.But really why? tex2D is expensive ? if yes, do you have any other idea instead of it.StreetLightsTex is a 16x16 float_32 texture.Don't forget if i want use global shader contants instead of a texture, then i must use a 16*16 float array , and i need also a hash function to found a light pos from the array, im not sure this give me a better result !However, now we are sure that tex2D in the "lookup" function reduce very of my FPS.Thank you for your attention.H.Ahmadi;  By removing that line, it looks like you're getting rid of 9 texture lookups, which is expensive. I usually try to keep my shaders under 3 lookups, however sometimes you need more.Also sm 2.0 does not support dynamic branching, where as sm 3.0 does. Which may be one of the reasons why it is faster using sm 3.0   ;  We did a mistake in last report about line 3 of "lookup" function, because changing it to float4(0,0,0,0) will cause that optimizer remove all of the function, because it's workflow detect that the function do nothing!!!   