Cycles: Implement threaded SVM nodes compilation
[blender.git] / intern / cycles / render / svm.h
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 #ifndef __SVM_H__
18 #define __SVM_H__
19
20 #include "attribute.h"
21 #include "graph.h"
22 #include "shader.h"
23
24 #include "util_set.h"
25 #include "util_string.h"
26 #include "util_thread.h"
27
28 CCL_NAMESPACE_BEGIN
29
30 class Device;
31 class DeviceScene;
32 class ImageManager;
33 class Scene;
34 class ShaderGraph;
35 class ShaderInput;
36 class ShaderNode;
37 class ShaderOutput;
38
39 /* Shader Manager */
40
41 class SVMShaderManager : public ShaderManager {
42 public:
43         SVMShaderManager();
44         ~SVMShaderManager();
45
46         void reset(Scene *scene);
47
48         void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
49         void device_free(Device *device, DeviceScene *dscene, Scene *scene);
50
51 protected:
52         /* Lock used to synchronize threaded nodes compilation. */
53         thread_spin_lock nodes_lock_;
54
55         void device_update_shader(Scene *scene,
56                                   Shader *shader,
57                                   Progress *progress,
58                                   vector<int4> *global_svm_nodes);
59 };
60
61 /* Graph Compiler */
62
63 class SVMCompiler {
64 public:
65         struct Summary {
66                 Summary();
67
68                 /* Number of SVM nodes shader was compiled into. */
69                 int num_svm_nodes;
70
71                 /* Peak stack usage during shader evaluation. */
72                 int peak_stack_usage;
73
74                 /* Time spent on surface graph finalization. */
75                 double time_finalize;
76
77                 /* Time spent on bump graph finalization. */
78                 double time_finalize_bump;
79
80                 /* Time spent on generating SVM nodes for surface shader. */
81                 double time_generate_surface;
82
83                 /* Time spent on generating SVM nodes for bump shader. */
84                 double time_generate_bump;
85
86                 /* Time spent on generating SVM nodes for volume shader. */
87                 double time_generate_volume;
88
89                 /* Time spent on generating SVM nodes for displacement shader. */
90                 double time_generate_displacement;
91
92                 /* Total time spent on all routines. */
93                 double time_total;
94
95                 /* A full multiline description of the state of the compiler after
96                  * compilation.
97                  */
98                 string full_report() const;
99         };
100
101         SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager);
102         void compile(Scene *scene,
103                      Shader *shader,
104                      vector<int4>& svm_nodes,
105                      int index,
106                      Summary *summary = NULL);
107
108         int stack_assign(ShaderOutput *output);
109         int stack_assign(ShaderInput *input);
110         int stack_assign_if_linked(ShaderInput *input);
111         int stack_assign_if_linked(ShaderOutput *output);
112         int stack_find_offset(int size);
113         int stack_find_offset(SocketType::Type type);
114         void stack_clear_offset(SocketType::Type type, int offset);
115         void stack_link(ShaderInput *input, ShaderOutput *output);
116
117         void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
118         void add_node(int a = 0, int b = 0, int c = 0, int d = 0);
119         void add_node(ShaderNodeType type, const float3& f);
120         void add_node(const float4& f);
121         uint attribute(ustring name);
122         uint attribute(AttributeStandard std);
123         uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
124         uint closure_mix_weight_offset() { return mix_weight_offset; }
125
126         ShaderType output_type() { return current_type; }
127
128         ImageManager *image_manager;
129         ShaderManager *shader_manager;
130         bool background;
131
132 protected:
133         /* stack */
134         struct Stack {
135                 Stack() { memset(users, 0, sizeof(users)); }
136                 Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); }
137                 Stack& operator=(const Stack& other) { memcpy(users, other.users, sizeof(users)); return *this; }
138
139                 bool empty()
140                 {
141                         for(int i = 0; i < SVM_STACK_SIZE; i++)
142                                 if(users[i])
143                                         return false;
144
145                         return true;
146                 }
147
148                 void print()
149                 {
150                         printf("stack <");
151
152                         for(int i = 0; i < SVM_STACK_SIZE; i++)
153                                 printf((users[i])? "*": " ");
154
155                         printf(">\n");
156                 }
157
158                 int users[SVM_STACK_SIZE];
159         };
160
161         /* Global state of the compiler accessible from the compilation routines. */
162         struct CompilerState {
163                 explicit CompilerState(ShaderGraph *graph);
164
165                 /* ** Global state, used by various compilation steps. ** */
166
167                 /* Set of nodes which were already compiled. */
168                 ShaderNodeSet nodes_done;
169
170                 /* Set of closures which were already compiled. */
171                 ShaderNodeSet closure_done;
172
173                 /* ** SVM nodes generation state ** */
174
175                 /* Flag whether the node with corresponding ID was already compiled or
176                  * not. Array element with index i corresponds to a node with such if.
177                  *
178                  * TODO(sergey): This is actually a copy of nodes_done just in another
179                  * notation. We can de-duplicate this storage actually after switching
180                  * all areas to use this flags array.
181                  */
182                 vector<bool> nodes_done_flag;
183         };
184
185         void stack_clear_temporary(ShaderNode *node);
186         int stack_size(SocketType::Type type);
187         void stack_clear_users(ShaderNode *node, ShaderNodeSet& done);
188
189         bool node_skip_input(ShaderNode *node, ShaderInput *input);
190
191         /* single closure */
192         void find_dependencies(ShaderNodeSet& dependencies,
193                                const ShaderNodeSet& done,
194                                ShaderInput *input,
195                                ShaderNode *skip_node = NULL);
196         void generate_node(ShaderNode *node, ShaderNodeSet& done);
197         void generate_closure_node(ShaderNode *node, CompilerState *state);
198         void generated_shared_closure_nodes(ShaderNode *root_node,
199                                             ShaderNode *node,
200                                             CompilerState *state,
201                                             const ShaderNodeSet& shared);
202         void generate_svm_nodes(const ShaderNodeSet& nodes,
203                                 CompilerState *state);
204
205         /* multi closure */
206         void generate_multi_closure(ShaderNode *root_node,
207                                     ShaderNode *node,
208                                     CompilerState *state);
209
210         /* compile */
211         void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
212
213         vector<int4> current_svm_nodes;
214         ShaderType current_type;
215         Shader *current_shader;
216         ShaderGraph *current_graph;
217         Stack active_stack;
218         int max_stack_use;
219         uint mix_weight_offset;
220         bool compile_failed;
221 };
222
223 CCL_NAMESPACE_END
224
225 #endif /* __SVM_H__ */
226