Fix some UI script errors after recent keyword changes.
[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 #undef MAP_PASS
477
478         return -1;
479 }
480
481 array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
482                                             BL::ViewLayer& b_view_layer,
483                                             const SessionParams &session_params)
484 {
485         array<Pass> passes;
486         Pass::add(PASS_COMBINED, passes);
487
488         if(!session_params.device.advanced_shading) {
489                 return passes;
490         }
491
492         /* loop over passes */
493         BL::RenderLayer::passes_iterator b_pass_iter;
494
495         for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
496                 BL::RenderPass b_pass(*b_pass_iter);
497                 PassType pass_type = get_pass_type(b_pass);
498
499                 if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
500                         continue;
501                 if(pass_type != PASS_NONE)
502                         Pass::add(pass_type, passes);
503         }
504
505         PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles");
506         if(get_boolean(crp, "denoising_store_passes") &&
507            get_boolean(crp, "use_denoising"))
508         {
509                 b_engine.add_pass("Denoising Normal",          3, "XYZ", b_view_layer.name().c_str());
510                 b_engine.add_pass("Denoising Normal Variance", 3, "XYZ", b_view_layer.name().c_str());
511                 b_engine.add_pass("Denoising Albedo",          3, "RGB", b_view_layer.name().c_str());
512                 b_engine.add_pass("Denoising Albedo Variance", 3, "RGB", b_view_layer.name().c_str());
513                 b_engine.add_pass("Denoising Depth",           1, "Z",   b_view_layer.name().c_str());
514                 b_engine.add_pass("Denoising Depth Variance",  1, "Z",   b_view_layer.name().c_str());
515                 b_engine.add_pass("Denoising Shadow A",        3, "XYV", b_view_layer.name().c_str());
516                 b_engine.add_pass("Denoising Shadow B",        3, "XYV", b_view_layer.name().c_str());
517                 b_engine.add_pass("Denoising Image",           3, "RGB", b_view_layer.name().c_str());
518                 b_engine.add_pass("Denoising Image Variance",  3, "RGB", b_view_layer.name().c_str());
519         }
520 #ifdef __KERNEL_DEBUG__
521         if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
522                 b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str());
523                 Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
524         }
525         if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
526                 b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str());
527                 Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
528         }
529         if(get_boolean(crp, "pass_debug_bvh_intersections")) {
530                 b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str());
531                 Pass::add(PASS_BVH_INTERSECTIONS, passes);
532         }
533         if(get_boolean(crp, "pass_debug_ray_bounces")) {
534                 b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str());
535                 Pass::add(PASS_RAY_BOUNCES, passes);
536         }
537 #endif
538         if(get_boolean(crp, "pass_debug_render_time")) {
539                 b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
540                 Pass::add(PASS_RENDER_TIME, passes);
541         }
542         if(get_boolean(crp, "use_pass_volume_direct")) {
543                 b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
544                 Pass::add(PASS_VOLUME_DIRECT, passes);
545         }
546         if(get_boolean(crp, "use_pass_volume_indirect")) {
547                 b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
548                 Pass::add(PASS_VOLUME_INDIRECT, passes);
549         }
550
551         return passes;
552 }
553
554 void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
555 {
556         /* When viewport display is not needed during render we can force some
557          * caches to be releases from blender side in order to reduce peak memory
558          * footprint during synchronization process.
559          */
560         const bool is_interface_locked = b_engine.render() &&
561                                          b_engine.render().use_lock_interface();
562         const bool can_free_caches = BlenderSession::headless || is_interface_locked;
563         if (!can_free_caches) {
564                 return;
565         }
566         /* TODO(sergey): We can actually remove the whole dependency graph,
567          * but that will need some API support first.
568          */
569         BL::Depsgraph::objects_iterator b_ob;
570         for(b_depsgraph.objects.begin(b_ob);
571             b_ob != b_depsgraph.objects.end();
572             ++b_ob)
573         {
574                 b_ob->cache_release();
575         }
576 }
577
578 /* Scene Parameters */
579
580 SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
581                                           bool background)
582 {
583         BL::RenderSettings r = b_scene.render();
584         SceneParams params;
585         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
586         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
587
588         if(shadingsystem == 0)
589                 params.shadingsystem = SHADINGSYSTEM_SVM;
590         else if(shadingsystem == 1)
591                 params.shadingsystem = SHADINGSYSTEM_OSL;
592
593         if(background || DebugFlags().viewport_static_bvh)
594                 params.bvh_type = SceneParams::BVH_STATIC;
595         else
596                 params.bvh_type = SceneParams::BVH_DYNAMIC;
597
598         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
599         params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
600         params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
601
602         if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
603                 params.persistent_data = r.use_persistent_data();
604         else
605                 params.persistent_data = false;
606
607         int texture_limit;
608         if(background) {
609                 texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
610         }
611         else {
612                 texture_limit = RNA_enum_get(&cscene, "texture_limit");
613         }
614         if(texture_limit > 0 && b_scene.render().use_simplify()) {
615                 params.texture_limit = 1 << (texture_limit + 6);
616         }
617         else {
618                 params.texture_limit = 0;
619         }
620
621         params.bvh_layout = DebugFlags().cpu.bvh_layout;
622
623         return params;
624 }
625
626 /* Session Parameters */
627
628 bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background)
629 {
630         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
631         return (background)? false: get_boolean(cscene, "preview_pause");
632 }
633
634 SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
635                                               BL::UserPreferences& b_userpref,
636                                               BL::Scene& b_scene,
637                                               bool background)
638 {
639         SessionParams params;
640         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
641
642         /* feature set */
643         params.experimental = (get_enum(cscene, "feature_set") != 0);
644
645         /* threads */
646         BL::RenderSettings b_r = b_scene.render();
647         if(b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED)
648                 params.threads = b_r.threads();
649         else
650                 params.threads = 0;
651
652         /* Background */
653         params.background = background;
654
655         /* device type */
656         vector<DeviceInfo>& devices = Device::available_devices();
657
658         /* device default CPU */
659         foreach(DeviceInfo& device, devices) {
660                 if(device.type == DEVICE_CPU) {
661                         params.device = device;
662                         break;
663                 }
664         }
665
666         if(get_enum(cscene, "device") == 2) {
667                 /* find network device */
668                 foreach(DeviceInfo& info, devices)
669                         if(info.type == DEVICE_NETWORK)
670                                 params.device = info;
671         }
672         else if(get_enum(cscene, "device") == 1) {
673                 PointerRNA b_preferences;
674
675                 BL::UserPreferences::addons_iterator b_addon_iter;
676                 for(b_userpref.addons.begin(b_addon_iter); b_addon_iter != b_userpref.addons.end(); ++b_addon_iter) {
677                         if(b_addon_iter->module() == "cycles") {
678                                 b_preferences = b_addon_iter->preferences().ptr;
679                                 break;
680                         }
681                 }
682
683                 enum ComputeDevice {
684                         COMPUTE_DEVICE_CPU = 0,
685                         COMPUTE_DEVICE_CUDA = 1,
686                         COMPUTE_DEVICE_OPENCL = 2,
687                         COMPUTE_DEVICE_NUM = 3,
688                 };
689
690                 ComputeDevice compute_device = (ComputeDevice)get_enum(b_preferences,
691                                                                        "compute_device_type",
692                                                                        COMPUTE_DEVICE_NUM,
693                                                                        COMPUTE_DEVICE_CPU);
694
695                 if(compute_device != COMPUTE_DEVICE_CPU) {
696                         vector<DeviceInfo> used_devices;
697                         RNA_BEGIN(&b_preferences, device, "devices") {
698                                 ComputeDevice device_type = (ComputeDevice)get_enum(device,
699                                                                                     "type",
700                                                                                     COMPUTE_DEVICE_NUM,
701                                                                                     COMPUTE_DEVICE_CPU);
702
703                                 if(get_boolean(device, "use") &&
704                                    (device_type == compute_device || device_type == COMPUTE_DEVICE_CPU)) {
705                                         string id = get_string(device, "id");
706                                         foreach(DeviceInfo& info, devices) {
707                                                 if(info.id == id) {
708                                                         used_devices.push_back(info);
709                                                         break;
710                                                 }
711                                         }
712                                 }
713                         } RNA_END
714
715                         if(used_devices.size() == 1) {
716                                 params.device = used_devices[0];
717                         }
718                         else if(used_devices.size() > 1) {
719                                 params.device = Device::get_multi_device(used_devices,
720                                                                          params.threads,
721                                                                          params.background);
722                         }
723                         /* Else keep using the CPU device that was set before. */
724                 }
725         }
726
727         /* samples */
728         int samples = get_int(cscene, "samples");
729         int aa_samples = get_int(cscene, "aa_samples");
730         int preview_samples = get_int(cscene, "preview_samples");
731         int preview_aa_samples = get_int(cscene, "preview_aa_samples");
732
733         if(get_boolean(cscene, "use_square_samples")) {
734                 aa_samples = aa_samples * aa_samples;
735                 preview_aa_samples = preview_aa_samples * preview_aa_samples;
736
737                 samples = samples * samples;
738                 preview_samples = preview_samples * preview_samples;
739         }
740
741         if(get_enum(cscene, "progressive") == 0) {
742                 if(background) {
743                         params.samples = aa_samples;
744                 }
745                 else {
746                         params.samples = preview_aa_samples;
747                         if(params.samples == 0)
748                                 params.samples = INT_MAX;
749                 }
750         }
751         else {
752                 if(background) {
753                         params.samples = samples;
754                 }
755                 else {
756                         params.samples = preview_samples;
757                         if(params.samples == 0)
758                                 params.samples = INT_MAX;
759                 }
760         }
761
762         /* tiles */
763         if(params.device.type != DEVICE_CPU && !background) {
764                 /* currently GPU could be much slower than CPU when using tiles,
765                  * still need to be investigated, but meanwhile make it possible
766                  * to work in viewport smoothly
767                  */
768                 int debug_tile_size = get_int(cscene, "debug_tile_size");
769
770                 params.tile_size = make_int2(debug_tile_size, debug_tile_size);
771         }
772         else {
773                 int tile_x = b_engine.tile_x();
774                 int tile_y = b_engine.tile_y();
775
776                 params.tile_size = make_int2(tile_x, tile_y);
777         }
778
779         if((BlenderSession::headless == false) && background) {
780                 params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
781         }
782         else {
783                 params.tile_order = TILE_BOTTOM_TO_TOP;
784         }
785
786         /* other parameters */
787         params.start_resolution = get_int(cscene, "preview_start_resolution");
788         params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
789
790         /* other parameters */
791         params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
792         params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
793         params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
794
795         /* progressive refine */
796         params.progressive_refine = (b_engine.is_preview() ||
797                                      get_boolean(cscene, "use_progressive_refine")) &&
798                                     !b_r.use_save_buffers();
799
800         if(params.progressive_refine) {
801                 BL::Scene::view_layers_iterator b_view_layer;
802                 for(b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) {
803                         PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles");
804                         if(get_boolean(crl, "use_denoising")) {
805                                 params.progressive_refine = false;
806                         }
807                 }
808         }
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                 params.pixel_size = 1;
818         }
819         else
820                 params.progressive = true;
821
822         /* shading system - scene level needs full refresh */
823         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
824
825         if(shadingsystem == 0)
826                 params.shadingsystem = SHADINGSYSTEM_SVM;
827         else if(shadingsystem == 1)
828                 params.shadingsystem = SHADINGSYSTEM_OSL;
829
830         /* color managagement */
831         params.display_buffer_linear = 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