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