Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / blender / blender_sync.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 "render/background.h"
18 #include "render/camera.h"
19 #include "render/film.h"
20 #include "render/graph.h"
21 #include "render/integrator.h"
22 #include "render/light.h"
23 #include "render/mesh.h"
24 #include "render/nodes.h"
25 #include "render/object.h"
26 #include "render/scene.h"
27 #include "render/shader.h"
28 #include "render/curves.h"
29
30 #include "device/device.h"
31
32 #include "blender/blender_sync.h"
33 #include "blender/blender_session.h"
34 #include "blender/blender_util.h"
35
36 #include "util/util_debug.h"
37 #include "util/util_foreach.h"
38 #include "util/util_opengl.h"
39 #include "util/util_hash.h"
40
41 CCL_NAMESPACE_BEGIN
42
43 /* Constructor */
44
45 BlenderSync::BlenderSync(BL::RenderEngine& b_engine,
46                          BL::BlendData& b_data,
47                          BL::Depsgraph& b_depsgraph,
48                          BL::Scene& b_scene,
49                          Scene *scene,
50                          bool preview,
51                          Progress &progress,
52                          bool is_cpu)
53 : b_engine(b_engine),
54   b_data(b_data),
55   b_depsgraph(b_depsgraph),
56   b_scene(b_scene),
57   b_scene_layer(b_engine.scene_layer()),
58   shader_map(&scene->shaders),
59   object_map(&scene->objects),
60   mesh_map(&scene->meshes),
61   light_map(&scene->lights),
62   particle_system_map(&scene->particle_systems),
63   world_map(NULL),
64   world_recalc(false),
65   scene(scene),
66   preview(preview),
67   experimental(false),
68   is_cpu(is_cpu),
69   dicing_rate(1.0f),
70   max_subdivisions(12),
71   progress(progress)
72 {
73         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
74         dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate");
75         max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
76 }
77
78 BlenderSync::~BlenderSync()
79 {
80 }
81
82 /* Sync */
83
84 bool BlenderSync::sync_recalc()
85 {
86         /* sync recalc flags from blender to cycles. actual update is done separate,
87          * so we can do it later on if doing it immediate is not suitable */
88
89         BL::BlendData::materials_iterator b_mat;
90         bool has_updated_objects = b_data.objects.is_updated();
91         for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
92                 if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) {
93                         shader_map.set_recalc(*b_mat);
94                 }
95                 else {
96                         Shader *shader = shader_map.find(*b_mat);
97                         if(has_updated_objects && shader != NULL && shader->has_object_dependency) {
98                                 shader_map.set_recalc(*b_mat);
99                         }
100                 }
101         }
102
103         BL::BlendData::lamps_iterator b_lamp;
104
105         for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
106                 if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
107                         shader_map.set_recalc(*b_lamp);
108
109         bool dicing_prop_changed = false;
110
111         if(experimental) {
112                 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
113
114                 float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate")
115                                                     : RNA_float_get(&cscene, "dicing_rate");
116
117                 if(dicing_rate != updated_dicing_rate) {
118                         dicing_rate = updated_dicing_rate;
119                         dicing_prop_changed = true;
120                 }
121
122                 int updated_max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
123
124                 if(max_subdivisions != updated_max_subdivisions) {
125                         max_subdivisions = updated_max_subdivisions;
126                         dicing_prop_changed = true;
127                 }
128         }
129
130         BL::BlendData::objects_iterator b_ob;
131
132         for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
133                 if(b_ob->is_updated()) {
134                         object_map.set_recalc(*b_ob);
135                         light_map.set_recalc(*b_ob);
136                 }
137
138                 if(object_is_mesh(*b_ob)) {
139                         if(b_ob->is_updated_data() || b_ob->data().is_updated() ||
140                            (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
141                         {
142                                 BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
143                                 mesh_map.set_recalc(key);
144                         }
145                 }
146                 else if(object_is_light(*b_ob)) {
147                         if(b_ob->is_updated_data() || b_ob->data().is_updated())
148                                 light_map.set_recalc(*b_ob);
149                 }
150                 
151                 if(b_ob->is_updated_data()) {
152                         BL::Object::particle_systems_iterator b_psys;
153                         for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
154                                 particle_system_map.set_recalc(*b_ob);
155                 }
156         }
157
158         BL::BlendData::meshes_iterator b_mesh;
159
160         for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) {
161                 if(b_mesh->is_updated()) {
162                         mesh_map.set_recalc(*b_mesh);
163                 }
164         }
165
166         BL::BlendData::worlds_iterator b_world;
167
168         for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
169                 if(world_map == b_world->ptr.data) {
170                         if(b_world->is_updated() ||
171                            (b_world->node_tree() && b_world->node_tree().is_updated()))
172                         {
173                                 world_recalc = true;
174                         }
175                         else if(b_world->node_tree() && b_world->use_nodes()) {
176                                 Shader *shader = scene->default_background;
177                                 if(has_updated_objects && shader->has_object_dependency) {
178                                         world_recalc = true;
179                                 }
180                         }
181                 }
182         }
183
184         bool recalc =
185                 shader_map.has_recalc() ||
186                 object_map.has_recalc() ||
187                 light_map.has_recalc() ||
188                 mesh_map.has_recalc() ||
189                 particle_system_map.has_recalc() ||
190                 BlendDataObjects_is_updated_get(&b_data.ptr) ||
191                 world_recalc;
192
193         return recalc;
194 }
195
196 void BlenderSync::sync_data(BL::RenderSettings& b_render,
197                             BL::SpaceView3D& b_v3d,
198                             BL::Object& b_override,
199                             int width, int height,
200                             void **python_thread_state,
201                             const char *layer)
202 {
203         sync_render_layers(b_v3d, layer);
204         sync_integrator();
205         sync_film();
206         sync_shaders();
207         sync_images();
208         sync_curve_settings();
209
210         mesh_synced.clear(); /* use for objects and motion sync */
211
212         if(scene->need_motion() == Scene::MOTION_PASS ||
213            scene->need_motion() == Scene::MOTION_NONE ||
214            scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
215         {
216                 sync_objects();
217         }
218         sync_motion(b_render,
219                     b_override,
220                     width, height,
221                     python_thread_state);
222
223         mesh_synced.clear();
224 }
225
226 /* Integrator */
227
228 void BlenderSync::sync_integrator()
229 {
230 #ifdef __CAMERA_MOTION__
231         BL::RenderSettings r = b_scene.render();
232 #endif
233         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
234
235         experimental = (get_enum(cscene, "feature_set") != 0);
236
237         Integrator *integrator = scene->integrator;
238         Integrator previntegrator = *integrator;
239
240         integrator->max_bounce = get_int(cscene, "max_bounces");
241
242         integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
243         integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
244         integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
245         integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
246
247         integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
248
249         integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
250         integrator->volume_step_size = get_float(cscene, "volume_step_size");
251
252         integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
253         integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
254         integrator->filter_glossy = get_float(cscene, "blur_glossy");
255
256         integrator->seed = get_int(cscene, "seed");
257         if(get_boolean(cscene, "use_animated_seed")) {
258                 integrator->seed = hash_int_2d(b_scene.frame_current(),
259                                                get_int(cscene, "seed"));
260                 if(b_scene.frame_subframe() != 0.0f) {
261                         /* TODO(sergey): Ideally should be some sort of hash_merge,
262                          * but this is good enough for now.
263                          */
264                         integrator->seed += hash_int_2d((int)(b_scene.frame_subframe() * (float)INT_MAX),
265                                                         get_int(cscene, "seed"));
266                 }
267         }
268
269         integrator->sampling_pattern = (SamplingPattern)get_enum(
270                 cscene,
271                 "sampling_pattern",
272                 SAMPLING_NUM_PATTERNS,
273                 SAMPLING_PATTERN_SOBOL);
274
275         integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
276         integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
277 #ifdef __CAMERA_MOTION__
278         if(!preview) {
279                 if(integrator->motion_blur != r.use_motion_blur()) {
280                         scene->object_manager->tag_update(scene);
281                         scene->camera->tag_update();
282                 }
283
284                 integrator->motion_blur = r.use_motion_blur();
285         }
286 #endif
287
288         integrator->method = (Integrator::Method)get_enum(cscene,
289                                                           "progressive",
290                                                           Integrator::NUM_METHODS,
291                                                           Integrator::PATH);
292
293         integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct");
294         integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
295         integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
296
297         int diffuse_samples = get_int(cscene, "diffuse_samples");
298         int glossy_samples = get_int(cscene, "glossy_samples");
299         int transmission_samples = get_int(cscene, "transmission_samples");
300         int ao_samples = get_int(cscene, "ao_samples");
301         int mesh_light_samples = get_int(cscene, "mesh_light_samples");
302         int subsurface_samples = get_int(cscene, "subsurface_samples");
303         int volume_samples = get_int(cscene, "volume_samples");
304
305         if(get_boolean(cscene, "use_square_samples")) {
306                 integrator->diffuse_samples = diffuse_samples * diffuse_samples;
307                 integrator->glossy_samples = glossy_samples * glossy_samples;
308                 integrator->transmission_samples = transmission_samples * transmission_samples;
309                 integrator->ao_samples = ao_samples * ao_samples;
310                 integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
311                 integrator->subsurface_samples = subsurface_samples * subsurface_samples;
312                 integrator->volume_samples = volume_samples * volume_samples;
313         } 
314         else {
315                 integrator->diffuse_samples = diffuse_samples;
316                 integrator->glossy_samples = glossy_samples;
317                 integrator->transmission_samples = transmission_samples;
318                 integrator->ao_samples = ao_samples;
319                 integrator->mesh_light_samples = mesh_light_samples;
320                 integrator->subsurface_samples = subsurface_samples;
321                 integrator->volume_samples = volume_samples;
322         }
323
324         if(b_scene.render().use_simplify()) {
325                 if(preview) {
326                         integrator->ao_bounces = get_int(cscene, "ao_bounces");
327                 }
328                 else {
329                         integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
330                 }
331         }
332         else {
333                 integrator->ao_bounces = 0;
334         }
335
336         if(integrator->modified(previntegrator))
337                 integrator->tag_update(scene);
338 }
339
340 /* Film */
341
342 void BlenderSync::sync_film()
343 {
344         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
345
346         Film *film = scene->film;
347         Film prevfilm = *film;
348         
349         film->exposure = get_float(cscene, "film_exposure");
350         film->filter_type = (FilterType)get_enum(cscene,
351                                                  "pixel_filter_type",
352                                                  FILTER_NUM_TYPES,
353                                                  FILTER_BLACKMAN_HARRIS);
354         film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
355
356         if(b_scene.world()) {
357                 BL::WorldMistSettings b_mist = b_scene.world().mist_settings();
358
359                 film->mist_start = b_mist.start();
360                 film->mist_depth = b_mist.depth();
361
362                 switch(b_mist.falloff()) {
363                         case BL::WorldMistSettings::falloff_QUADRATIC:
364                                 film->mist_falloff = 2.0f;
365                                 break;
366                         case BL::WorldMistSettings::falloff_LINEAR:
367                                 film->mist_falloff = 1.0f;
368                                 break;
369                         case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC:
370                                 film->mist_falloff = 0.5f;
371                                 break;
372                 }
373         }
374
375         if(film->modified(prevfilm))
376                 film->tag_update(scene);
377 }
378
379 /* Render Layer */
380
381 void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer)
382 {
383         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
384         string layername;
385
386         /* 3d view */
387         if(b_v3d) {
388                 BL::RenderLayers layers(b_scene.render().ptr);
389                 layername = layers.active().name();
390                 layer = layername.c_str();
391         }
392
393         /* render layer */
394         BL::RenderSettings r = b_scene.render();
395         BL::RenderSettings::layers_iterator b_rlay;
396         int use_layer_samples = get_enum(cscene, "use_layer_samples");
397         bool first_layer = true;
398         uint layer_override = get_layer(b_engine.layer_override());
399         uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers());
400
401         for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
402                 if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
403                         render_layer.name = b_rlay->name();
404
405                         render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
406                         render_layer.exclude_layer = get_layer(b_rlay->layers_exclude());
407
408                         render_layer.scene_layer = scene_layers & ~render_layer.exclude_layer;
409                         render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer;
410
411                         render_layer.layer = get_layer(b_rlay->layers());
412                         render_layer.layer |= render_layer.holdout_layer;
413
414                         render_layer.material_override = b_rlay->material_override();
415                         render_layer.use_background_shader = b_rlay->use_sky();
416                         render_layer.use_background_ao = b_rlay->use_ao();
417                         render_layer.use_surfaces = b_rlay->use_solid();
418                         render_layer.use_hair = b_rlay->use_strand();
419
420                         render_layer.bound_samples = (use_layer_samples == 1);
421                         if(use_layer_samples != 2) {
422                                 int samples = b_rlay->samples();
423                                 if(get_boolean(cscene, "use_square_samples"))
424                                         render_layer.samples = samples * samples;
425                                 else
426                                         render_layer.samples = samples;
427                         }
428                 }
429
430                 first_layer = false;
431         }
432 }
433
434 /* Images */
435 void BlenderSync::sync_images()
436 {
437         /* Sync is a convention for this API, but currently it frees unused buffers. */
438
439         const bool is_interface_locked = b_engine.render() &&
440                                          b_engine.render().use_lock_interface();
441         if(is_interface_locked == false && BlenderSession::headless == false) {
442                 /* If interface is not locked, it's possible image is needed for
443                  * the display.
444                  */
445                 return;
446         }
447         /* Free buffers used by images which are not needed for render. */
448         BL::BlendData::images_iterator b_image;
449         for(b_data.images.begin(b_image);
450             b_image != b_data.images.end();
451             ++b_image)
452         {
453                 /* TODO(sergey): Consider making it an utility function to check
454                  * whether image is considered builtin.
455                  */
456                 const bool is_builtin = b_image->packed_file() ||
457                                         b_image->source() == BL::Image::source_GENERATED ||
458                                         b_image->source() == BL::Image::source_MOVIE ||
459                                         b_engine.is_preview();
460                 if(is_builtin == false) {
461                         b_image->buffers_free();
462                 }
463                 /* TODO(sergey): Free builtin images not used by any shader. */
464         }
465 }
466
467 /* Passes */
468 PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
469 {
470         string name = b_pass.name();
471 #define MAP_PASS(passname, passtype) if(name == passname) return passtype;
472         /* NOTE: Keep in sync with defined names from DNA_scene_types.h */
473         MAP_PASS("Combined", PASS_COMBINED);
474         MAP_PASS("Depth", PASS_DEPTH);
475         MAP_PASS("Mist", PASS_MIST);
476         MAP_PASS("Normal", PASS_NORMAL);
477         MAP_PASS("IndexOB", PASS_OBJECT_ID);
478         MAP_PASS("UV", PASS_UV);
479         MAP_PASS("Vector", PASS_MOTION);
480         MAP_PASS("IndexMA", PASS_MATERIAL_ID);
481
482         MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
483         MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
484         MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
485         MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT);
486
487         MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
488         MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
489         MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
490         MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT);
491
492         MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
493         MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
494         MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
495         MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR);
496
497         MAP_PASS("Emit", PASS_EMISSION);
498         MAP_PASS("Env", PASS_BACKGROUND);
499         MAP_PASS("AO", PASS_AO);
500         MAP_PASS("Shadow", PASS_SHADOW);
501
502 #ifdef __KERNEL_DEBUG__
503         MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
504         MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
505         MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS);
506         MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
507 #endif
508 #undef MAP_PASS
509
510         return PASS_NONE;
511 }
512
513 int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
514 {
515         string name = b_pass.name();
516         if(name.substr(0, 10) != "Denoising ") {
517                 return -1;
518         }
519         name = name.substr(10);
520
521 #define MAP_PASS(passname, offset) if(name == passname) return offset;
522         MAP_PASS("Normal", DENOISING_PASS_NORMAL);
523         MAP_PASS("Normal Variance", DENOISING_PASS_NORMAL_VAR);
524         MAP_PASS("Albedo", DENOISING_PASS_ALBEDO);
525         MAP_PASS("Albedo Variance", DENOISING_PASS_ALBEDO_VAR);
526         MAP_PASS("Depth", DENOISING_PASS_DEPTH);
527         MAP_PASS("Depth Variance", DENOISING_PASS_DEPTH_VAR);
528         MAP_PASS("Shadow A", DENOISING_PASS_SHADOW_A);
529         MAP_PASS("Shadow B", DENOISING_PASS_SHADOW_B);
530         MAP_PASS("Image", DENOISING_PASS_COLOR);
531         MAP_PASS("Image Variance", DENOISING_PASS_COLOR_VAR);
532 #undef MAP_PASS
533
534         return -1;
535 }
536
537 array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
538                                             BL::SceneRenderLayer& b_srlay,
539                                             const SessionParams &session_params)
540 {
541         array<Pass> passes;
542         Pass::add(PASS_COMBINED, passes);
543
544         if(!session_params.device.advanced_shading) {
545                 return passes;
546         }
547
548         /* loop over passes */
549         BL::RenderLayer::passes_iterator b_pass_iter;
550
551         for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
552                 BL::RenderPass b_pass(*b_pass_iter);
553                 PassType pass_type = get_pass_type(b_pass);
554
555                 if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
556                         continue;
557                 if(pass_type != PASS_NONE)
558                         Pass::add(pass_type, passes);
559         }
560
561         PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
562         if(get_boolean(crp, "denoising_store_passes") &&
563            get_boolean(crp, "use_denoising") &&
564            !session_params.progressive_refine) {
565                 b_engine.add_pass("Denoising Normal",          3, "XYZ", b_srlay.name().c_str());
566                 b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_srlay.name().c_str());
567                 b_engine.add_pass("Denoising Albedo",          3, "RGB", b_srlay.name().c_str());
568                 b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_srlay.name().c_str());
569                 b_engine.add_pass("Denoising Depth",           1, "Z",   b_srlay.name().c_str());
570                 b_engine.add_pass("Denoising Depth Variance",  1, "Z",   b_srlay.name().c_str());
571                 b_engine.add_pass("Denoising Shadow A",        3, "XYV", b_srlay.name().c_str());
572                 b_engine.add_pass("Denoising Shadow B",        3, "XYV", b_srlay.name().c_str());
573                 b_engine.add_pass("Denoising Image",           3, "RGB", b_srlay.name().c_str());
574                 b_engine.add_pass("Denoising Image Variance",  3, "RGB", b_srlay.name().c_str());
575         }
576 #ifdef __KERNEL_DEBUG__
577         if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
578                 b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str());
579                 Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
580         }
581         if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
582                 b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str());
583                 Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
584         }
585         if(get_boolean(crp, "pass_debug_bvh_intersections")) {
586                 b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str());
587                 Pass::add(PASS_BVH_INTERSECTIONS, passes);
588         }
589         if(get_boolean(crp, "pass_debug_ray_bounces")) {
590                 b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
591                 Pass::add(PASS_RAY_BOUNCES, passes);
592         }
593 #endif
594
595         return passes;
596 }
597
598 /* Scene Parameters */
599
600 SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
601                                           bool background,
602                                           bool is_cpu)
603 {
604         BL::RenderSettings r = b_scene.render();
605         SceneParams params;
606         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
607         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
608
609         if(shadingsystem == 0)
610                 params.shadingsystem = SHADINGSYSTEM_SVM;
611         else if(shadingsystem == 1)
612                 params.shadingsystem = SHADINGSYSTEM_OSL;
613         
614         if(background)
615                 params.bvh_type = SceneParams::BVH_STATIC;
616         else
617                 params.bvh_type = (SceneParams::BVHType)get_enum(
618                         cscene,
619                         "debug_bvh_type",
620                         SceneParams::BVH_NUM_TYPES,
621                         SceneParams::BVH_STATIC);
622
623         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
624         params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
625         params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
626
627         if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
628                 params.persistent_data = r.use_persistent_data();
629         else
630                 params.persistent_data = false;
631
632         int texture_limit;
633         if(background) {
634                 texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
635         }
636         else {
637                 texture_limit = RNA_enum_get(&cscene, "texture_limit");
638         }
639         if(texture_limit > 0 && b_scene.render().use_simplify()) {
640                 params.texture_limit = 1 << (texture_limit + 6);
641         }
642         else {
643                 params.texture_limit = 0;
644         }
645
646 #if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
647         if(is_cpu) {
648                 params.use_qbvh = DebugFlags().cpu.qbvh && system_cpu_support_sse2();
649         }
650         else
651 #endif
652         {
653                 params.use_qbvh = false;
654         }
655
656         return params;
657 }
658
659 /* Session Parameters */
660
661 bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background)
662 {
663         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
664         return (background)? false: get_boolean(cscene, "preview_pause");
665 }
666
667 SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
668                                               BL::UserPreferences& b_userpref,
669                                               BL::Scene& b_scene,
670                                               bool background)
671 {
672         SessionParams params;
673         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
674
675         /* feature set */
676         params.experimental = (get_enum(cscene, "feature_set") != 0);
677
678         /* device type */
679         vector<DeviceInfo>& devices = Device::available_devices();
680         
681         /* device default CPU */
682         foreach(DeviceInfo& device, devices) {
683                 if(device.type == DEVICE_CPU) {
684                         params.device = device;
685                         break;
686                 }
687         }
688
689         if(get_enum(cscene, "device") == 2) {
690                 /* find network device */
691                 foreach(DeviceInfo& info, devices)
692                         if(info.type == DEVICE_NETWORK)
693                                 params.device = info;
694         }
695         else if(get_enum(cscene, "device") == 1) {
696                 PointerRNA b_preferences;
697
698                 BL::UserPreferences::addons_iterator b_addon_iter;
699                 for(b_userpref.addons.begin(b_addon_iter); b_addon_iter != b_userpref.addons.end(); ++b_addon_iter) {
700                         if(b_addon_iter->module() == "cycles") {
701                                 b_preferences = b_addon_iter->preferences().ptr;
702                                 break;
703                         }
704                 }
705
706                 int compute_device = get_enum(b_preferences, "compute_device_type");
707
708                 if(compute_device != 0) {
709                         vector<DeviceInfo> used_devices;
710                         RNA_BEGIN(&b_preferences, device, "devices") {
711                                 if(get_enum(device, "type") == compute_device && get_boolean(device, "use")) {
712                                         string id = get_string(device, "id");
713                                         foreach(DeviceInfo& info, devices) {
714                                                 if(info.id == id) {
715                                                         used_devices.push_back(info);
716                                                         break;
717                                                 }
718                                         }
719                                 }
720                         } RNA_END
721
722                         if(used_devices.size() == 1) {
723                                 params.device = used_devices[0];
724                         }
725                         else if(used_devices.size() > 1) {
726                                 params.device = Device::get_multi_device(used_devices);
727                         }
728                         /* Else keep using the CPU device that was set before. */
729                 }
730         }
731
732         /* Background */
733         params.background = background;
734
735         /* samples */
736         int samples = get_int(cscene, "samples");
737         int aa_samples = get_int(cscene, "aa_samples");
738         int preview_samples = get_int(cscene, "preview_samples");
739         int preview_aa_samples = get_int(cscene, "preview_aa_samples");
740         
741         if(get_boolean(cscene, "use_square_samples")) {
742                 aa_samples = aa_samples * aa_samples;
743                 preview_aa_samples = preview_aa_samples * preview_aa_samples;
744
745                 samples = samples * samples;
746                 preview_samples = preview_samples * preview_samples;
747         }
748
749         if(get_enum(cscene, "progressive") == 0) {
750                 if(background) {
751                         params.samples = aa_samples;
752                 }
753                 else {
754                         params.samples = preview_aa_samples;
755                         if(params.samples == 0)
756                                 params.samples = INT_MAX;
757                 }
758         }
759         else {
760                 if(background) {
761                         params.samples = samples;
762                 }
763                 else {
764                         params.samples = preview_samples;
765                         if(params.samples == 0)
766                                 params.samples = INT_MAX;
767                 }
768         }
769
770         /* tiles */
771         if(params.device.type != DEVICE_CPU && !background) {
772                 /* currently GPU could be much slower than CPU when using tiles,
773                  * still need to be investigated, but meanwhile make it possible
774                  * to work in viewport smoothly
775                  */
776                 int debug_tile_size = get_int(cscene, "debug_tile_size");
777
778                 params.tile_size = make_int2(debug_tile_size, debug_tile_size);
779         }
780         else {
781                 int tile_x = b_engine.tile_x();
782                 int tile_y = b_engine.tile_y();
783
784                 params.tile_size = make_int2(tile_x, tile_y);
785         }
786
787         if((BlenderSession::headless == false) && background) {
788                 params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
789         }
790         else {
791                 params.tile_order = TILE_BOTTOM_TO_TOP;
792         }
793
794         params.start_resolution = get_int(cscene, "preview_start_resolution");
795
796         /* other parameters */
797         if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
798                 params.threads = b_scene.render().threads();
799         else
800                 params.threads = 0;
801
802         params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
803         params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
804         params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
805
806         params.progressive_refine = get_boolean(cscene, "use_progressive_refine");
807
808         if(background) {
809                 if(params.progressive_refine)
810                         params.progressive = true;
811                 else
812                         params.progressive = false;
813
814                 params.start_resolution = INT_MAX;
815         }
816         else
817                 params.progressive = true;
818
819         /* shading system - scene level needs full refresh */
820         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
821
822         if(shadingsystem == 0)
823                 params.shadingsystem = SHADINGSYSTEM_SVM;
824         else if(shadingsystem == 1)
825                 params.shadingsystem = SHADINGSYSTEM_OSL;
826         
827         /* color managagement */
828         params.display_buffer_linear = GLEW_ARB_half_float_pixel &&
829                                        b_engine.support_display_space_shader(b_scene);
830
831         if(b_engine.is_preview()) {
832                 /* For preview rendering we're using same timeout as
833                  * blender's job update.
834                  */
835                 params.progressive_update_timeout = 0.1;
836         }
837
838         return params;
839 }
840
841 CCL_NAMESPACE_END
842