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