# DX11 - Weird shader behavior with and without branching

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

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

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

``````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);
``````
-
Smells like premature optimization though. –  Jonathan Dickinson Apr 23 '12 at 10:36
You could also write `val = lerp(X2, X1, tmp)`, slightly more compact. –  Nathan Reed Jun 26 '12 at 21:40
@NathanReed I didn't even realise that it was effectively the same equation as a lerp. Many thanks. –  Jonathan Dickinson 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.

-
+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. –  JohnB Jun 27 '12 at 10:56
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. –  Darth Melkor Jun 27 '12 at 12:11