HLSL if-statement

Started by
9 comments, last by gogogigo 15 years, 2 months ago
My Compiler always stops at the easiest if-statement (phongshader) : float4 std_PS(vertexOutput IN) : COLOR { float3 diffContrib; float3 specContrib; float3 Ln = normalize(IN.LightVec); float3 Vn = normalize(IN.WorldView); float3 Nn = normalize(IN.WorldNormal); phong_shading(IN,Lamp0Color,Nn,Ln,Vn,diffContrib,specContrib); float3 diffuseColor = tex2D(ColorSampler,IN.UV).rgb; float3 result = specContrib * 0.9 +(diffuseColor*(diffContrib+AmbiColor)); if (result.x == 1.0f) return float4(1.0f,1.0f,1.0f,1.0f); // <-- Here it stops return float4(result/100,1); } When I replace the last 2 rows with: if (1.0f == 1.0f) return float4(1.0f,1.0f,1.0f,1.0f); return float4(result/100,1); ... there is no Problem I Use vs_3_0 and ps_3_0 and Visual Basic.NET. Why does my Compiler stops??
Advertisement
This would be a typical 'you tell me?' scenario. How do you compile your shaders? What parameters do you use? What does the compiler give as output?

Now, if I had to take a wild guess, I'd say you have something bad in the function phong_shading, or perhaps you go over the PS instruction limit, which in PS_3_0 is 512. If you use the if(1.0f == 1.0f) return float4(1,1,1,1); line, the HLSL FX compiler will see that being always true, and it will just discard *ALL* (assuming you have default optimizations on) of your pixel shader code and replace that with a simple return float4(1,1,1,1); statement, which compiles fine.

But really, that's just a guess. If you're able to post more specific information, someone can probably help better.
I might be wrong but I dont think PS 3.0 supports conditional returns.

The reason it would work when you put in a tautology like if 1=1 is that compiler would optimze that statement out.

instead, just use the conditional to compute a float4 finalcolor.rgb and return that.
Thanks, but there's still the same problem, even if I reduce the Shader to these lines:

float4x4 WvpXf : WorldViewProjection;

texture ColorTexture : DIFFUSE;
sampler2D ColorSampler = sampler_state {
Texture = <ColorTexture>;
AddressU = Wrap;
AddressV = Wrap;
};

struct appdata {
float3 Position : POSITION;
float4 UV : TEXCOORD0;

};

struct vertexOutput {
float4 HPosition : POSITION;
float2 UV : TEXCOORD0;
};

vertexOutput std_VS(appdata IN) {
vertexOutput OUT;
OUT.UV = IN.UV.xy;
OUT.HPosition = mul(float4(IN.Position.xyz,1),WvpXf);
return OUT;
}

float4 std_PS(vertexOutput IN) : COLOR {
float3 diffuseColor = tex2D(ColorSampler,IN.UV).rgb;
if (diffuseColor.x) return float4(1,1,1,1); ///////// <====
return float4(diffuseColor,1);
}

technique Main {
pass p0 {
VertexShader = compile vs_3_0 std_VS(); // or vs_2_0
PixelShader = compile ps_3_0 std_PS(); // or ps_2_0
}
}



This Shader works perfect in NVidia FXComposer, but not in my program.
The Error is/are in my program:

...\phong.fx(76): error X3500: asymetric returns from if statements not yet implemented
...\phong.fx(85): ID3DXEffectCompiler::CompileEffect: There was an error compiling expression
ID3DXEffectCompiler: Compilation failed

I can't do anything with this description.
I compile the Shader with the (managed) function Effect.FromFile ( Shaderflags.Debug)

I relatively unfamiliar with the HLSL syntax, but does the 'return' keyword in HLSL the same like it would in say C++, C#, VB?

If so, then that would explain the behavior:

// original source but reformatedfloat4 std_PS(vertexOutput IN) : COLOR {  float3 diffContrib;  float3 specContrib;  float3 Ln = normalize(IN.LightVec);  float3 Vn = normalize(IN.WorldView);  float3 Nn = normalize(IN.WorldNormal);  phong_shading(IN,Lamp0Color,Nn,Ln,Vn,diffContrib,specContrib);  float3 diffuseColor = tex2D(ColorSampler,IN.UV).rgb;  float3 result = specContrib * 0.9 +(diffuseColor*(diffContrib+AmbiColor));  if (result.x == 1.0f)     return float4(1.0f,1.0f,1.0f,1.0f); // <-- Here it stops  return float4(result/100,1);}

Put it like this:

float4 outValue = float4(result/100,1);
if (result.x == 1.0f) outValue = float4(1.0f,1.0f,1.0f,1.0f);
return outValue;
}

Usually compiler will allow you to use several "return" but only at the end of the shader and only first one will actually work. Practically it means that only one "return" can be used.
if (result.x == 1.0f)

Dont think this will solve your problems but you should avoid using equal/not-equal with floating point numbers anyway.
.
Quote:
The Error is/are in my program:

...\phong.fx(76): error X3500: asymetric returns from if statements not yet implemented
...\phong.fx(85): ID3DXEffectCompiler::CompileEffect: There was an error compiling expression
ID3DXEffectCompiler: Compilation failed

I can't do anything with this description.
I compile the Shader with the (managed) function Effect.FromFile ( Shaderflags.Debug)


My guess would be that the compiler doesn't like it if your "if" branch returns something and your "else" branch does not.
Simple test for that would be to put an "else" before your final return statement.
I'm just guessing what could be meant by "asymmetrical returns from if statements", though.
If that isn't a solution at all or not for your case, I'd just go with Viik's solution.
Yeah, the missing else part is the problem. I had the error myself some time ago.
Are you using XNA? The FX compiler used by XNA is out of date and doesn't support conditional returns. Check this post at the xna forums on how to use the latest FX compiler: Link

This topic is closed to new replies.

Advertisement