Cycles: Add fundamentals to test constant folding
[blender.git] / intern / cycles / render / constant_fold.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "constant_fold.h"
18 #include "graph.h"
19
20 #include "util_foreach.h"
21 #include "util_logging.h"
22
23 CCL_NAMESPACE_BEGIN
24
25 ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output)
26 : graph(graph), node(node), output(output)
27 {
28 }
29
30 bool ConstantFolder::all_inputs_constant() const
31 {
32         foreach(ShaderInput *input, node->inputs) {
33                 if(input->link) {
34                         return false;
35                 }
36         }
37
38         return true;
39 }
40
41 void ConstantFolder::make_constant(float value) const
42 {
43         VLOG(1) << "Replacing " << node->name << " with constant " << value << ".";
44         foreach(ShaderInput *sock, output->links) {
45                 sock->set(value);
46         }
47
48         graph->disconnect(output);
49 }
50
51 void ConstantFolder::make_constant(float3 value) const
52 {
53         foreach(ShaderInput *sock, output->links) {
54                 sock->set(value);
55         }
56
57         graph->disconnect(output);
58 }
59
60 void ConstantFolder::make_constant_clamp(float value, bool clamp) const
61 {
62         make_constant(clamp ? saturate(value) : value);
63 }
64
65 void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
66 {
67         if (clamp) {
68                 value.x = saturate(value.x);
69                 value.y = saturate(value.y);
70                 value.z = saturate(value.z);
71         }
72
73         make_constant(value);
74 }
75
76 void ConstantFolder::bypass(ShaderOutput *new_output) const
77 {
78         assert(new_output);
79
80         /* Remove all outgoing links from socket and connect them to new_output instead.
81          * The graph->relink method affects node inputs, so it's not safe to use in constant
82          * folding if the node has multiple outputs and will thus be folded multiple times. */
83         vector<ShaderInput*> outputs = output->links;
84
85         graph->disconnect(output);
86
87         foreach(ShaderInput *sock, outputs) {
88                 graph->connect(new_output, sock);
89         }
90 }
91
92 void ConstantFolder::discard() const
93 {
94         assert(output->type() == SocketType::CLOSURE);
95         graph->disconnect(output);
96 }
97
98 void ConstantFolder::bypass_or_discard(ShaderInput *input) const
99 {
100         assert(input->type() == SocketType::CLOSURE);
101
102         if (input->link) {
103                 bypass(input->link);
104         }
105         else {
106                 discard();
107         }
108 }
109
110 bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, float3 input_value, bool clamp) const
111 {
112         if(!input->link) {
113                 make_constant_clamp(input_value, clamp);
114                 return true;
115         }
116         else if(!clamp) {
117                 bypass(input->link);
118                 return true;
119         }
120
121         return false;
122 }
123
124 CCL_NAMESPACE_END