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