"If" node versus "custom" one with "a>b" and similar operations

Hi guys :slight_smile:

Does “if” node really cost a bit more performance rather that “custom” node with a code:
return (a>b);

I read that article http://www.froyok.fr/blog/2017-03-st…ng-the-if-node

But as we also know, “custom” node itself are can be a bit more expensive, even with a dead simple code like add, divide, etc.

No.

No on this one too.

Froyok’s article is a bit misleading, namely the part where IF material expression is compared against custom node.
It will be translated to different code, depending if equals pin is connected or not. If it is, expression will be translated to a heavier code, that does comparison with threshold in mind.

This is straigth from documantation:
Using the custom node prevents constant folding and may use significantly more instructions than an equivalent version done with built in nodes! Constant folding is an optimization that UE4 employs under the hood to reduce shader instruction count when necessary. For example, an expression chain of Time >Sin >Mul by parameter > Add to something can and will be collapsed by UE4 into a single instruction, the final add. This is possible because all of the inputs of that expression (Time, parameter) are constant for the whole draw call, they do not change per-pixel. UE4 cannot collapse anything in a custom node, which can produce less efficient shaders than an equivalent version made out of existing nodes. As a result, it is best to only use the custom node when it gives you access to functionality not possible with the existing nodes.

That would still be no. Custom node does not prevent constant folding. Documentation is worded a bit off and is interpreted in a wrong way.
Unreal’s material translator has a system, that evaluates the graph and if any parts of the graph are uniform(thus, being the same for all shader executions), replaces it with a value, that is calculated on CPU.
Custom material expression will never evaluate to a uniform material expression, and likewise, anything done within it won’t and this is the part documentation refers to. Shader compiler constant folding though will not be affected by custom node.

Guess what? You can move out all uniform operations with shader parameters out of custom node and keep them in the graph. So custom node being slower is myths and legends, provided, that you understand which parts of your graph are uniform.

Besides, the example from documentation page, namely Time->Sine->Mul by scalar is also wrong, as it will be not be evaluated as uniform.

1 Like

First time I’m seeing anything else related to this topic (finally!).

I believe it’s ok to assume that constant folding is done only during compilation, but the documentation is presented as it’s being done before every draw call so CPU computes it once and then it does not have to be done for everypixel within that drawcall.

I’m not sure what to believe here. It’s obviously doable, but it would require some kind of preprepared register to let cpu know what to compute without the need to parse stuff again, which I doubt is done.

So I’d go with compilation constant folding only, which would mean the documentation is wrong on the Time->Sin->Mul->Add by parameter. However, uniform buffers are rebuilt every frame, so it’s not like it’s impossible to store it as a “constant”.

I’m not really feeling going through that part of the codebase though

If you don’t want to use the IF node, a cheaper alternative is to use Elias Wick | Conditional Statements. However, keep in mind that the IF node definitely has it’s uses at times when necessary.