0
\$\begingroup\$

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

\$\endgroup\$
2
  • 1
    \$\begingroup\$ How about some screenshots? What exactly is the problem? This looks like over micro-optimization. \$\endgroup\$
    – ashes999
    Apr 23, 2012 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, 2012 at 9:52

2 Answers 2

4
\$\begingroup\$

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);
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Smells like premature optimization though. \$\endgroup\$ Apr 23, 2012 at 10:36
  • 1
    \$\begingroup\$ You could also write val = lerp(X2, X1, tmp), slightly more compact. \$\endgroup\$ Jun 26, 2012 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, 2012 at 10:11
3
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\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, 2012 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, 2012 at 12:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .