Fix #33107: cycles fixed threads 1 was still having two cores do work,
[blender.git] / intern / cycles / blender / blender_sync.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 "background.h"
20 #include "camera.h"
21 #include "film.h"
22 #include "../render/filter.h"
23 #include "graph.h"
24 #include "integrator.h"
25 #include "light.h"
26 #include "mesh.h"
27 #include "nodes.h"
28 #include "object.h"
29 #include "scene.h"
30 #include "shader.h"
31
32 #include "device.h"
33
34 #include "blender_sync.h"
35 #include "blender_util.h"
36
37 #include "util_debug.h"
38 #include "util_foreach.h"
39
40 CCL_NAMESPACE_BEGIN
41
42 /* Constructor */
43
44 BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
45 : b_engine(b_engine_),
46   b_data(b_data_), b_scene(b_scene_),
47   shader_map(&scene_->shaders),
48   object_map(&scene_->objects),
49   mesh_map(&scene_->meshes),
50   light_map(&scene_->lights),
51   particle_system_map(&scene_->particle_systems),
52   world_map(NULL),
53   world_recalc(false),
54   experimental(false),
55   progress(progress_)
56 {
57         scene = scene_;
58         preview = preview_;
59 }
60
61 BlenderSync::~BlenderSync()
62 {
63 }
64
65 /* Sync */
66
67 bool BlenderSync::sync_recalc()
68 {
69         /* sync recalc flags from blender to cycles. actual update is done separate,
70          * so we can do it later on if doing it immediate is not suitable */
71
72         BL::BlendData::materials_iterator b_mat;
73
74         for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat)
75                 if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated()))
76                         shader_map.set_recalc(*b_mat);
77
78         BL::BlendData::lamps_iterator b_lamp;
79
80         for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
81                 if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
82                         shader_map.set_recalc(*b_lamp);
83
84         BL::BlendData::objects_iterator b_ob;
85
86         for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
87                 if(b_ob->is_updated()) {
88                         object_map.set_recalc(*b_ob);
89                         light_map.set_recalc(*b_ob);
90                 }
91
92                 if(object_is_mesh(*b_ob)) {
93                         if(b_ob->is_updated_data() || b_ob->data().is_updated()) {
94                                 BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
95                                 mesh_map.set_recalc(key);
96                         }
97                 }
98                 else if(object_is_light(*b_ob)) {
99                         if(b_ob->is_updated_data() || b_ob->data().is_updated())
100                                 light_map.set_recalc(*b_ob);
101                 }
102                 
103                 if(b_ob->is_updated_data()) {
104                         BL::Object::particle_systems_iterator b_psys;
105                         for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
106                                 particle_system_map.set_recalc(*b_ob);
107                 }
108         }
109
110         BL::BlendData::meshes_iterator b_mesh;
111
112         for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh)
113                 if(b_mesh->is_updated())
114                         mesh_map.set_recalc(*b_mesh);
115
116         BL::BlendData::worlds_iterator b_world;
117
118         for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
119                 if(world_map == b_world->ptr.data &&
120                    (b_world->is_updated() || (b_world->node_tree() && b_world->node_tree().is_updated())))
121                 {
122                         world_recalc = true;
123                 }
124         }
125
126         bool recalc =
127                 shader_map.has_recalc() ||
128                 object_map.has_recalc() ||
129                 light_map.has_recalc() ||
130                 mesh_map.has_recalc() ||
131                 particle_system_map.has_recalc() ||
132                 BlendDataObjects_is_updated_get(&b_data.ptr) ||
133                 world_recalc;
134
135         return recalc;
136 }
137
138 void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const char *layer)
139 {
140         sync_render_layers(b_v3d, layer);
141         sync_integrator();
142         sync_film();
143         sync_shaders();
144         sync_objects(b_v3d);
145         sync_motion(b_v3d, b_override);
146 }
147
148 /* Integrator */
149
150 void BlenderSync::sync_integrator()
151 {
152 #ifdef __CAMERA_MOTION__
153         BL::RenderSettings r = b_scene.render();
154 #endif
155         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
156
157         experimental = (RNA_enum_get(&cscene, "feature_set") != 0);
158
159         Integrator *integrator = scene->integrator;
160         Integrator previntegrator = *integrator;
161
162         integrator->min_bounce = get_int(cscene, "min_bounces");
163         integrator->max_bounce = get_int(cscene, "max_bounces");
164
165         integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
166         integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
167         integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
168
169         integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
170         integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
171         integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
172
173         integrator->no_caustics = get_boolean(cscene, "no_caustics");
174         integrator->filter_glossy = get_float(cscene, "blur_glossy");
175
176         integrator->seed = get_int(cscene, "seed");
177
178         integrator->layer_flag = render_layer.layer;
179
180         integrator->sample_clamp = get_float(cscene, "sample_clamp");
181 #ifdef __CAMERA_MOTION__
182         if(integrator->motion_blur != r.use_motion_blur()) {
183                 scene->object_manager->tag_update(scene);
184                 scene->camera->tag_update();
185         }
186
187         integrator->motion_blur = (!preview && r.use_motion_blur());
188 #endif
189
190         integrator->diffuse_samples = get_int(cscene, "diffuse_samples");
191         integrator->glossy_samples = get_int(cscene, "glossy_samples");
192         integrator->transmission_samples = get_int(cscene, "transmission_samples");
193         integrator->ao_samples = get_int(cscene, "ao_samples");
194         integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples");
195         integrator->progressive = get_boolean(cscene, "progressive");
196
197         if(integrator->modified(previntegrator))
198                 integrator->tag_update(scene);
199 }
200
201 /* Film */
202
203 void BlenderSync::sync_film()
204 {
205         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
206
207         Film *film = scene->film;
208         Film prevfilm = *film;
209
210         film->exposure = get_float(cscene, "film_exposure");
211
212         if(film->modified(prevfilm))
213                 film->tag_update(scene);
214
215         Filter *filter = scene->filter;
216         Filter prevfilter = *filter;
217
218         filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
219         filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
220
221         if(filter->modified(prevfilter))
222                 filter->tag_update(scene);
223 }
224
225 /* Render Layer */
226
227 void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
228 {
229         string layername;
230
231         /* 3d view */
232         if(b_v3d) {
233                 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
234
235                 if(RNA_boolean_get(&cscene, "preview_active_layer")) {
236                         BL::RenderLayers layers(b_scene.render().ptr);
237                         layername = layers.active().name();
238                         layer = layername.c_str();
239                 }
240                 else {
241                         render_layer.use_localview = (b_v3d.local_view() ? true : false);
242                         render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview);
243                         render_layer.layer = render_layer.scene_layer;
244                         render_layer.holdout_layer = 0;
245                         render_layer.material_override = PointerRNA_NULL;
246                         render_layer.use_background = true;
247                         render_layer.use_viewport_visibility = true;
248                         render_layer.samples = 0;
249                         return;
250                 }
251         }
252
253         /* render layer */
254         BL::RenderSettings r = b_scene.render();
255         BL::RenderSettings::layers_iterator b_rlay;
256         bool first_layer = true;
257
258         for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
259                 if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
260                         render_layer.name = b_rlay->name();
261                         render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude());
262                         render_layer.layer = get_layer(b_rlay->layers());
263                         render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
264                         render_layer.layer |= render_layer.holdout_layer;
265                         render_layer.material_override = b_rlay->material_override();
266                         render_layer.use_background = b_rlay->use_sky();
267                         render_layer.use_viewport_visibility = false;
268                         render_layer.use_localview = false;
269                         render_layer.samples = b_rlay->samples();
270                 }
271
272                 first_layer = false;
273         }
274 }
275
276 /* Scene Parameters */
277
278 SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background)
279 {
280         SceneParams params;
281         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
282         int shadingsystem = RNA_enum_get(&cscene, "shading_system");
283
284         if(shadingsystem == 0)
285                 params.shadingsystem = SceneParams::SVM;
286         else if(shadingsystem == 1)
287                 params.shadingsystem = SceneParams::OSL;
288         
289         if(background)
290                 params.bvh_type = SceneParams::BVH_STATIC;
291         else
292                 params.bvh_type = (SceneParams::BVHType)RNA_enum_get(&cscene, "debug_bvh_type");
293
294         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
295         params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false;
296
297         return params;
298 }
299
300 /* Session Parameters */
301
302 bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
303 {
304         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
305         return (background)? false: get_boolean(cscene, "preview_pause");
306 }
307
308 SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
309 {
310         SessionParams params;
311         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
312
313         /* feature set */
314         params.experimental = (RNA_enum_get(&cscene, "feature_set") != 0);
315
316         /* device type */
317         vector<DeviceInfo>& devices = Device::available_devices();
318         
319         /* device default CPU */
320         params.device = devices[0];
321
322         if(RNA_enum_get(&cscene, "device") != 0) {
323                 /* find GPU device with given id */
324                 PointerRNA systemptr = b_userpref.system().ptr;
325                 PropertyRNA *deviceprop = RNA_struct_find_property(&systemptr, "compute_device");
326                 int device_id = b_userpref.system().compute_device();
327
328                 const char *id;
329
330                 if(RNA_property_enum_identifier(NULL, &systemptr, deviceprop, device_id, &id)) {
331                         foreach(DeviceInfo& info, devices)
332                                 if(info.id == id)
333                                         params.device = info;
334                 }
335         }
336
337         /* Background */
338         params.background = background;
339
340         /* samples */
341         if(get_boolean(cscene, "progressive")) {
342                 if(background) {
343                         params.samples = get_int(cscene, "samples");
344                 }
345                 else {
346                         params.samples = get_int(cscene, "preview_samples");
347                         if(params.samples == 0)
348                                 params.samples = INT_MAX;
349                 }
350         }
351         else {
352                 if(background) {
353                         params.samples = get_int(cscene, "aa_samples");
354                 }
355                 else {
356                         params.samples = get_int(cscene, "preview_aa_samples");
357                         if(params.samples == 0)
358                                 params.samples = INT_MAX;
359                 }
360         }
361
362         /* tiles */
363         if(params.device.type != DEVICE_CPU && !background) {
364                 /* currently GPU could be much slower than CPU when using tiles,
365                  * still need to be investigated, but meanwhile make it possible
366                  * to work in viewport smoothly
367                  */
368                 int debug_tile_size = get_int(cscene, "debug_tile_size");
369
370                 params.tile_size = make_int2(debug_tile_size, debug_tile_size);
371         }
372         else {
373                 int tile_x = b_engine.tile_x();
374                 int tile_y = b_engine.tile_y();
375
376                 params.tile_size = make_int2(tile_x, tile_y);
377         }
378
379         params.start_resolution = get_int(cscene, "preview_start_resolution");
380
381         /* other parameters */
382         if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
383                 params.threads = b_scene.render().threads();
384         else
385                 params.threads = 0;
386
387         params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
388         params.reset_timeout = get_float(cscene, "debug_reset_timeout");
389         params.text_timeout = get_float(cscene, "debug_text_timeout");
390
391         params.progressive_refine = get_boolean(cscene, "use_progressive_refine");
392
393         if(background) {
394                 if(params.progressive_refine)
395                         params.progressive = true;
396                 else
397                         params.progressive = false;
398
399                 params.start_resolution = INT_MAX;
400         }
401         else
402                 params.progressive = true;
403
404         /* shading system - scene level needs full refresh */
405         int shadingsystem = RNA_enum_get(&cscene, "shading_system");
406
407         if(shadingsystem == 0)
408                 params.shadingsystem = SessionParams::SVM;
409         else if(shadingsystem == 1)
410                 params.shadingsystem = SessionParams::OSL;
411
412         return params;
413 }
414
415 CCL_NAMESPACE_END
416