Fix #33405: preview render getting stuck in a particular .blend file, ObjectKey
[blender.git] / intern / cycles / render / shader.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "device.h"
20 #include "graph.h"
21 #include "light.h"
22 #include "mesh.h"
23 #include "nodes.h"
24 #include "osl.h"
25 #include "scene.h"
26 #include "shader.h"
27 #include "svm.h"
28
29 #include "util_foreach.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 /* Shader */
34
35 Shader::Shader()
36 {
37         name = "";
38         pass_id = 0;
39
40         graph = NULL;
41         graph_bump = NULL;
42
43         sample_as_light = true;
44         homogeneous_volume = false;
45
46         has_surface = false;
47         has_surface_transparent = false;
48         has_surface_emission = false;
49         has_volume = false;
50         has_displacement = false;
51
52         used = false;
53
54         need_update = true;
55         need_update_attributes = true;
56 }
57
58 Shader::~Shader()
59 {
60         delete graph;
61         delete graph_bump;
62 }
63
64 void Shader::set_graph(ShaderGraph *graph_)
65 {
66         /* assign graph */
67         delete graph;
68         delete graph_bump;
69         graph = graph_;
70         graph_bump = NULL;
71 }
72
73 void Shader::tag_update(Scene *scene)
74 {
75         /* update tag */
76         need_update = true;
77         scene->shader_manager->need_update = true;
78
79         /* if the shader previously was emissive, update light distribution,
80          * if the new shader is emissive, a light manager update tag will be
81          * done in the shader manager device update. */
82         if(sample_as_light && has_surface_emission)
83                 scene->light_manager->need_update = true;
84
85         /* get requested attributes. this could be optimized by pruning unused
86          * nodes here already, but that's the job of the shader manager currently,
87          * and may not be so great for interactive rendering where you temporarily
88          * disconnect a node */
89         AttributeRequestSet prev_attributes = attributes;
90
91         attributes.clear();
92         foreach(ShaderNode *node, graph->nodes)
93                 node->attributes(&attributes);
94         
95         /* compare if the attributes changed, mesh manager will check
96          * need_update_attributes, update the relevant meshes and clear it. */
97         if(attributes.modified(prev_attributes)) {
98                 need_update_attributes = true;
99                 scene->mesh_manager->need_update = true;
100         }
101 }
102
103 void Shader::tag_used(Scene *scene)
104 {
105         /* if an unused shader suddenly gets used somewhere, it needs to be
106          * recompiled because it was skipped for compilation before */
107         if(!used) {
108                 need_update = true;
109                 scene->shader_manager->need_update = true;
110         }
111 }
112
113 /* Shader Manager */
114
115 ShaderManager::ShaderManager()
116 {
117         need_update = true;
118 }
119
120 ShaderManager::~ShaderManager()
121 {
122 }
123
124 ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
125 {
126         ShaderManager *manager;
127
128 #ifdef WITH_OSL
129         if(shadingsystem == SceneParams::OSL)
130                 manager = new OSLShaderManager();
131         else
132 #endif
133                 manager = new SVMShaderManager();
134         
135         add_default(scene);
136
137         return manager;
138 }
139
140 uint ShaderManager::get_attribute_id(ustring name)
141 {
142         /* get a unique id for each name, for SVM attribute lookup */
143         AttributeIDMap::iterator it = unique_attribute_id.find(name);
144
145         if(it != unique_attribute_id.end())
146                 return it->second;
147         
148         uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
149         unique_attribute_id[name] = id;
150         return id;
151 }
152
153 uint ShaderManager::get_attribute_id(AttributeStandard std)
154 {
155         return (uint)std;
156 }
157
158 int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
159 {
160         /* get a shader id to pass to the kernel */
161         int id = shader*2;
162         
163         /* index depends bump since this setting is not in the shader */
164         if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
165                 id += 1;
166         /* smooth flag */
167         if(smooth)
168                 id |= SHADER_SMOOTH_NORMAL;
169         
170         /* default flags */
171         id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
172         
173         return id;
174 }
175
176 void ShaderManager::device_update_shaders_used(Scene *scene)
177 {
178         /* figure out which shaders are in use, so SVM/OSL can skip compiling them
179          * for speed and avoid loading image textures into memory */
180         foreach(Shader *shader, scene->shaders)
181                 shader->used = false;
182
183         scene->shaders[scene->default_surface]->used = true;
184         scene->shaders[scene->default_light]->used = true;
185         scene->shaders[scene->default_background]->used = true;
186         scene->shaders[scene->default_holdout]->used = true;
187         scene->shaders[scene->default_empty]->used = true;
188
189         foreach(Mesh *mesh, scene->meshes)
190                 foreach(uint shader, mesh->used_shaders)
191                         scene->shaders[shader]->used = true;
192
193         foreach(Light *light, scene->lights)
194                 scene->shaders[light->shader]->used = true;
195 }
196
197 void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
198 {
199         device_free_common(device, dscene);
200
201         if(scene->shaders.size() == 0)
202                 return;
203
204         uint shader_flag_size = scene->shaders.size()*4;
205         uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
206         uint i = 0;
207
208         foreach(Shader *shader, scene->shaders) {
209                 uint flag = 0;
210
211                 if(shader->sample_as_light)
212                         flag |= SD_SAMPLE_AS_LIGHT;
213                 if(shader->has_surface_transparent)
214                         flag |= SD_HAS_SURFACE_TRANSPARENT;
215                 if(shader->has_volume)
216                         flag |= SD_HAS_VOLUME;
217                 if(shader->homogeneous_volume)
218                         flag |= SD_HOMOGENEOUS_VOLUME;
219
220                 shader_flag[i++] = flag;
221                 shader_flag[i++] = shader->pass_id;
222                 shader_flag[i++] = flag;
223                 shader_flag[i++] = shader->pass_id;
224         }
225
226         device->tex_alloc("__shader_flag", dscene->shader_flag);
227 }
228
229 void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
230 {
231         device->tex_free(dscene->shader_flag);
232         dscene->shader_flag.clear();
233 }
234
235 void ShaderManager::add_default(Scene *scene)
236 {
237         Shader *shader;
238         ShaderGraph *graph;
239         ShaderNode *closure, *out;
240
241         /* default surface */
242         {
243                 graph = new ShaderGraph();
244
245                 closure = graph->add(new DiffuseBsdfNode());
246                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
247                 out = graph->output();
248
249                 graph->connect(closure->output("BSDF"), out->input("Surface"));
250
251                 shader = new Shader();
252                 shader->name = "default_surface";
253                 shader->graph = graph;
254                 scene->shaders.push_back(shader);
255                 scene->default_surface = scene->shaders.size() - 1;
256         }
257
258         /* default light */
259         {
260                 graph = new ShaderGraph();
261
262                 closure = graph->add(new EmissionNode());
263                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
264                 closure->input("Strength")->value.x = 0.0f;
265                 out = graph->output();
266
267                 graph->connect(closure->output("Emission"), out->input("Surface"));
268
269                 shader = new Shader();
270                 shader->name = "default_light";
271                 shader->graph = graph;
272                 scene->shaders.push_back(shader);
273                 scene->default_light = scene->shaders.size() - 1;
274         }
275
276         /* default background */
277         {
278                 graph = new ShaderGraph();
279
280                 closure = graph->add(new BackgroundNode());
281                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
282                 out = graph->output();
283
284                 graph->connect(closure->output("Background"), out->input("Surface"));
285
286                 shader = new Shader();
287                 shader->name = "default_background";
288                 shader->graph = graph;
289                 scene->shaders.push_back(shader);
290                 scene->default_background = scene->shaders.size() - 1;
291         }
292
293         /* default holdout */
294         {
295                 graph = new ShaderGraph();
296
297                 closure = graph->add(new HoldoutNode());
298                 out = graph->output();
299
300                 graph->connect(closure->output("Holdout"), out->input("Surface"));
301
302                 shader = new Shader();
303                 shader->name = "default_holdout";
304                 shader->graph = graph;
305                 scene->shaders.push_back(shader);
306                 scene->default_holdout = scene->shaders.size() - 1;
307         }
308
309         /* default empty */
310         {
311                 graph = new ShaderGraph();
312
313                 shader = new Shader();
314                 shader->name = "default_empty";
315                 shader->graph = graph;
316                 scene->shaders.push_back(shader);
317                 scene->default_empty = scene->shaders.size() - 1;
318         }
319 }
320
321 CCL_NAMESPACE_END
322