These values often either turn the node into a no-op, or even make it
evaluate to 0 no matter what the other input value is, thus allowing
deletion of a branch of the node graph that otherwise is not constant.
Details
- Reviewers
Thomas Dinges (dingto) Sergey Sharybin (sergey) Alexander Gavrilov (angavrilov) - Group Reviewers
Cycles - Commits
- rC6df55047f4e0: constant fold add/mul type nodes with known 0 and 1 arguments.
rBS1776f75c3b36: Cycles: constant fold add/mul type nodes with known 0 and 1 arguments.
rB1776f75c3b36: Cycles: constant fold add/mul type nodes with known 0 and 1 arguments.
Diff Detail
- Repository
- rB Blender
- Branch
- arcpatch-D2085
- Build Status
Buildable 66 Build 66: arc lint + arc unit
Event Timeline
Generally fine, but personally find confusing following things:
- Meaning and semantic of partial_fold() is unclear and nowhere documented.
- There's quite some code which seems to be duplication of what we've got in kernel. Those chunks are also not really small and makes code more tricky to navigate. Perhaps it is time to introduce node_optimize.{cpp,h} and move such checks for whether something can be optimized out there.
| intern/cycles/render/nodes.cpp | ||
|---|---|---|
| 3707 | This doesn't follow code convention. There should be no space between keyword and brace in Cycles. | |
| 3710 | I'm tempting to ask to always use parenthesis in new code. There are various advantages to that. | |
| 4593 | Comment is a full sentence, starting with capital and ending up with fullstop, | |
I am against the addition of a partial_fold() method just for this particular case. It should be handled inside of constant_fold() like the others. Don't see a good reason to have constant and partial fold functions.
- Meaning and semantic of partial_fold() is unclear and nowhere documented.
It's very simple: one of the two main arguments is a constant; check if it allows to fold or remove the node no matter what the other argument is. Arguments are correspondingly the constant argument, pointer to the 'other' argument, and whatever else needed to perform the fold. The method could be called 'one_side_fold' or similar instead.
For multiplication and addition this is completely symmetrical, while subtraction and division only work one side, thus the argidx argument. This could be replaced by an is_left or is_right bool. I judged that handling assymetry through this parameter result overall in smallest amount of extra code.
- There's quite some code which seems to be duplication of what we've got in kernel. Those chunks are also not really small and makes code more tricky to navigate. Perhaps it is time to introduce node_optimize.{cpp,h} and move such checks for whether something can be optimized out there.
Hm, I doubt that the kernel contains any code detecting multiplication or addition of zero as a special case - or is this about some other code?
It feels like duplication of evaluation code. In any case, those chunks i think belongs to some other place for the code simplicity in nodes compilation. It could be an utility function which will check whether the operation can be omitted.\ and give some extra tips how to omit it. This will also avoid need in partial_fold() since code will be small enough to be done in constant_fold().
It feels like duplication of evaluation code.
Constant folding is inevitably some duplication of evaluation code, unless you are writing a compiler within an interpreter (like common lisp) and can just dynamically call the evaluation code at compile time.
In any case, those chunks i think belongs to some other place for the code simplicity in nodes compilation. It could be an utility function which will check whether the operation can be omitted.\ and give some extra tips how to omit it. This will also avoid need in partial_fold() since code will be small enough to be done in constant_fold().
I cannot see any way the amount of code can be reduced by that. The switch is unavoidable as it's the thing that decides if it can be folded, and the folding code does the folding with variations between the three nodes because of clamp and fac. The main reason partial_fold can't just be put into constant_fold is that constant_fold can call it for either of the two arguments, and the parameters are swapped in these cases. If you want to put it into constant_fold, that implicit swapping via call arguments will have to become a bunch of explicit assignments, actually increasing code size.
I had an idea though: one minor thing that actually can decrease the amount of boiler plate in constant folding are two helper functions. One would do optimized->set(...) and return true, the other call graph->relink and return true. That would dispense with the need to have { ...; return true; } all over the place, instead allowing e.g. return fold_as_value(optimized, value);.
I'm talking about minimizing code in nodes.cpp file by moving utilities function to another file. nodes.cpp is already quite long and unfun to navigate in. Adding rather big evaluation functions to it will make it even less fun.
Surely amount of code needed to perform cosntant fold stays the same, but it can be arranged in a way which simplifies reading, not complicating it.
If we're going to split up nodes.cpp I'd rather split different nodes into different files. Like nodes_input.cpp, nodes_shader.cpp, nodes_texture.cpp, following the Blender node categories.
But I would suggest that if we decide to split up nodes.cpp, we can still commit this patch first, no need to hold things up. If we come to a decision on how to split things up and no one else is interested in doing it, I'm happy to do it.
| intern/cycles/render/nodes.cpp | ||
|---|---|---|
| 3703–3704 | No need to mark these static. | |
| intern/cycles/render/nodes.cpp | ||
|---|---|---|
| 3703–3704 | The idea of static was to make these actual constants. An even better thing would be to have it at the start of the file, or in some header perhaps. | |
Also fold "X - X" like setups to 0.
Brecht had an idea to make automated tests for folding by including an OSL shader node that fails unless it is folded away, and this new rule can be used to detect folding to bypass.
Refactored to make folding logic easier to follow, at least in my opinion this
is easier to read and verify to be correct.
I intend to commit this still for 2.78.