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