I have found problem in my shader code, which I dont´t know how to solve.

I want to rewrite this code without "ifs"

tmp = evaluate and result is 0 or 1 (nothing else)
if (tmp == 1) val = X1;
if (tmp == 0) val = X2;

I rewite it this way, but this piece of code doesn ´t word correctly

tmp = evaluate and result is 0 or 1 (nothing else)
val = tmp * X1
val = !tmp * X2

However if I change it to:

tmp = evaluate and result is 0 or 1 (nothing else)
val = tmp * X1
if (!tmp) val = !tmp * X2

It works fine... but it is useless because of "if", which need to be eliminated

I honestly don´t understand it Posted Image . I tried compilation with NO and FULL optimalization, result is same

  • 1
    \$\begingroup\$ How about some screenshots? What exactly is the problem? This looks like over micro-optimization. \$\endgroup\$
    – ashes999
    Apr 23 '12 at 9:37
  • \$\begingroup\$ I don't know what is operators precedence in HLSL, but can you try: val = (!tmp) * X2 ? \$\endgroup\$
    – zacharmarz
    Apr 23 '12 at 9:52

Your problem is: !1 == -2, not !1 == 0.

Try this instead:

val = tmp * X1;
val += (1 - tmp) * X2;

This works because:

1 * x = x

(1 - 1) * x = 
   0    * x = 0


0 * x = 0

(1 - 0) * x = 
   1    * x = x

As suggested by Nathan, to make the code more compact you can use lerp. The equation for lerp is (a * (1 - c)) + (b * c) which is identical to the equation you see above. Thus the code would become:

val = lerp(X2, X1, tmp);
  • 1
    \$\begingroup\$ Smells like premature optimization though. \$\endgroup\$ Apr 23 '12 at 10:36
  • 1
    \$\begingroup\$ You could also write val = lerp(X2, X1, tmp), slightly more compact. \$\endgroup\$ Jun 26 '12 at 21:40
  • \$\begingroup\$ @NathanReed I didn't even realise that it was effectively the same equation as a lerp. Many thanks. \$\endgroup\$ Jun 28 '12 at 10:11

I'd advise to just write it with regular branching in your shader code. The D3D shader compiler is extremely good at taking code like this and converting it to a non-branching equivalent in bytecode, and can also detect cases (they're rare but they do happen) where a branching solution is actually faster than a non-branching one. You definitely shouldn't assume that just because your HLSL code uses branching it means that the generated shader will also branch - have a look at the asm version of your shader in PIX and you may be in for an eye-opener - they can often be quite different.

It will also be much more maintainable going forward than if you do anything tricksy to avoid branches in HLSL code.

  • \$\begingroup\$ +1 on this. I was suprised when I looked at my shaders how few of my branches ended up as branches in the generated code. \$\endgroup\$
    – JohnB
    Jun 27 '12 at 10:56
  • \$\begingroup\$ This is actually the definition of why premature optimization is evil - not because it's premature and not because it's optimization, but because it's trying to second-guess what the compiler/environment will do and creating a mess (maybe a small mess, but still a mess) while doing so. \$\endgroup\$ Jun 27 '12 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.