ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / blender / blender_session.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 <stdlib.h>
18
19 #include "render/background.h"
20 #include "render/buffers.h"
21 #include "render/camera.h"
22 #include "device/device.h"
23 #include "render/integrator.h"
24 #include "render/film.h"
25 #include "render/light.h"
26 #include "render/mesh.h"
27 #include "render/object.h"
28 #include "render/scene.h"
29 #include "render/session.h"
30 #include "render/shader.h"
31 #include "render/stats.h"
32
33 #include "util/util_algorithm.h"
34 #include "util/util_color.h"
35 #include "util/util_foreach.h"
36 #include "util/util_function.h"
37 #include "util/util_hash.h"
38 #include "util/util_logging.h"
39 #include "util/util_murmurhash.h"
40 #include "util/util_progress.h"
41 #include "util/util_time.h"
42
43 #include "blender/blender_sync.h"
44 #include "blender/blender_session.h"
45 #include "blender/blender_util.h"
46
47 CCL_NAMESPACE_BEGIN
48
49 bool BlenderSession::headless = false;
50 int BlenderSession::num_resumable_chunks = 0;
51 int BlenderSession::current_resumable_chunk = 0;
52 int BlenderSession::start_resumable_chunk = 0;
53 int BlenderSession::end_resumable_chunk = 0;
54 bool BlenderSession::print_render_stats = false;
55
56 BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
57                                BL::Preferences &b_userpref,
58                                BL::BlendData &b_data,
59                                bool preview_osl)
60     : session(NULL),
61       sync(NULL),
62       b_engine(b_engine),
63       b_userpref(b_userpref),
64       b_data(b_data),
65       b_render(b_engine.render()),
66       b_depsgraph(PointerRNA_NULL),
67       b_scene(PointerRNA_NULL),
68       b_v3d(PointerRNA_NULL),
69       b_rv3d(PointerRNA_NULL),
70       width(0),
71       height(0),
72       preview_osl(preview_osl),
73       python_thread_state(NULL)
74 {
75   /* offline render */
76   background = true;
77   last_redraw_time = 0.0;
78   start_resize_time = 0.0;
79   last_status_time = 0.0;
80 }
81
82 BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
83                                BL::Preferences &b_userpref,
84                                BL::BlendData &b_data,
85                                BL::SpaceView3D &b_v3d,
86                                BL::RegionView3D &b_rv3d,
87                                int width,
88                                int height)
89     : session(NULL),
90       sync(NULL),
91       b_engine(b_engine),
92       b_userpref(b_userpref),
93       b_data(b_data),
94       b_render(b_engine.render()),
95       b_depsgraph(PointerRNA_NULL),
96       b_scene(PointerRNA_NULL),
97       b_v3d(b_v3d),
98       b_rv3d(b_rv3d),
99       width(width),
100       height(height),
101       preview_osl(false),
102       python_thread_state(NULL)
103 {
104   /* 3d view render */
105   background = false;
106   last_redraw_time = 0.0;
107   start_resize_time = 0.0;
108   last_status_time = 0.0;
109 }
110
111 BlenderSession::~BlenderSession()
112 {
113   free_session();
114 }
115
116 void BlenderSession::create()
117 {
118   create_session();
119 }
120
121 void BlenderSession::create_session()
122 {
123   SessionParams session_params = BlenderSync::get_session_params(
124       b_engine, b_userpref, b_scene, background);
125   SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
126   bool session_pause = BlenderSync::get_session_pause(b_scene, background);
127
128   /* reset status/progress */
129   last_status = "";
130   last_error = "";
131   last_progress = -1.0f;
132   start_resize_time = 0.0;
133
134   /* create session */
135   session = new Session(session_params);
136   session->scene = scene;
137   session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
138   session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
139   session->set_pause(session_pause);
140
141   /* create scene */
142   scene = new Scene(scene_params, session->device);
143   scene->name = b_scene.name();
144
145   /* setup callbacks for builtin image support */
146   scene->image_manager->builtin_image_info_cb = function_bind(
147       &BlenderSession::builtin_image_info, this, _1, _2, _3);
148   scene->image_manager->builtin_image_pixels_cb = function_bind(
149       &BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
150   scene->image_manager->builtin_image_float_pixels_cb = function_bind(
151       &BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
152
153   session->scene = scene;
154
155   /* There is no single depsgraph to use for the entire render.
156    * So we need to handle this differently.
157    *
158    * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers,
159    * or perhaps move syncing further down in the pipeline.
160    */
161   /* create sync */
162   sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
163   BL::Object b_camera_override(b_engine.camera_override());
164   if (b_v3d) {
165     sync->sync_view(b_v3d, b_rv3d, width, height);
166   }
167   else {
168     sync->sync_camera(b_render, b_camera_override, width, height, "");
169   }
170
171   /* set buffer parameters */
172   BufferParams buffer_params = BlenderSync::get_buffer_params(
173       b_render, b_v3d, b_rv3d, scene->camera, width, height);
174   session->reset(buffer_params, session_params.samples);
175
176   b_engine.use_highlight_tiles(session_params.progressive_refine == false);
177
178   update_resumable_tile_manager(session_params.samples);
179 }
180
181 void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
182 {
183   this->b_data = b_data;
184   this->b_depsgraph = b_depsgraph;
185   this->b_scene = b_depsgraph.scene_eval();
186
187   if (preview_osl) {
188     PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
189     RNA_boolean_set(&cscene, "shading_system", preview_osl);
190   }
191
192   if (b_v3d) {
193     this->b_render = b_scene.render();
194   }
195   else {
196     this->b_render = b_engine.render();
197     width = render_resolution_x(b_render);
198     height = render_resolution_y(b_render);
199   }
200
201   if (session == NULL) {
202     create();
203   }
204
205   if (b_v3d) {
206     /* NOTE: We need to create session, but all the code from below
207      * will make viewport render to stuck on initialization.
208      */
209     return;
210   }
211
212   SessionParams session_params = BlenderSync::get_session_params(
213       b_engine, b_userpref, b_scene, background);
214   SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
215
216   if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
217       !scene_params.persistent_data) {
218     /* if scene or session parameters changed, it's easier to simply re-create
219      * them rather than trying to distinguish which settings need to be updated
220      */
221     free_session();
222     create_session();
223     return;
224   }
225
226   session->progress.reset();
227   scene->reset();
228
229   session->tile_manager.set_tile_order(session_params.tile_order);
230
231   /* peak memory usage should show current render peak, not peak for all renders
232    * made by this render session
233    */
234   session->stats.mem_peak = session->stats.mem_used;
235
236   /* There is no single depsgraph to use for the entire render.
237    * See note on create_session().
238    */
239   /* sync object should be re-created */
240   sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
241
242   BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
243   BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
244   BufferParams buffer_params = BlenderSync::get_buffer_params(
245       b_render, b_null_space_view3d, b_null_region_view3d, scene->camera, width, height);
246   session->reset(buffer_params, session_params.samples);
247
248   b_engine.use_highlight_tiles(session_params.progressive_refine == false);
249
250   /* reset time */
251   start_resize_time = 0.0;
252 }
253
254 void BlenderSession::free_session()
255 {
256   if (sync)
257     delete sync;
258
259   delete session;
260 }
261
262 static ShaderEvalType get_shader_type(const string &pass_type)
263 {
264   const char *shader_type = pass_type.c_str();
265
266   /* data passes */
267   if (strcmp(shader_type, "NORMAL") == 0)
268     return SHADER_EVAL_NORMAL;
269   else if (strcmp(shader_type, "UV") == 0)
270     return SHADER_EVAL_UV;
271   else if (strcmp(shader_type, "ROUGHNESS") == 0)
272     return SHADER_EVAL_ROUGHNESS;
273   else if (strcmp(shader_type, "DIFFUSE_COLOR") == 0)
274     return SHADER_EVAL_DIFFUSE_COLOR;
275   else if (strcmp(shader_type, "GLOSSY_COLOR") == 0)
276     return SHADER_EVAL_GLOSSY_COLOR;
277   else if (strcmp(shader_type, "TRANSMISSION_COLOR") == 0)
278     return SHADER_EVAL_TRANSMISSION_COLOR;
279   else if (strcmp(shader_type, "SUBSURFACE_COLOR") == 0)
280     return SHADER_EVAL_SUBSURFACE_COLOR;
281   else if (strcmp(shader_type, "EMIT") == 0)
282     return SHADER_EVAL_EMISSION;
283
284   /* light passes */
285   else if (strcmp(shader_type, "AO") == 0)
286     return SHADER_EVAL_AO;
287   else if (strcmp(shader_type, "COMBINED") == 0)
288     return SHADER_EVAL_COMBINED;
289   else if (strcmp(shader_type, "SHADOW") == 0)
290     return SHADER_EVAL_SHADOW;
291   else if (strcmp(shader_type, "DIFFUSE") == 0)
292     return SHADER_EVAL_DIFFUSE;
293   else if (strcmp(shader_type, "GLOSSY") == 0)
294     return SHADER_EVAL_GLOSSY;
295   else if (strcmp(shader_type, "TRANSMISSION") == 0)
296     return SHADER_EVAL_TRANSMISSION;
297   else if (strcmp(shader_type, "SUBSURFACE") == 0)
298     return SHADER_EVAL_SUBSURFACE;
299
300   /* extra */
301   else if (strcmp(shader_type, "ENVIRONMENT") == 0)
302     return SHADER_EVAL_ENVIRONMENT;
303
304   else
305     return SHADER_EVAL_BAKE;
306 }
307
308 static BL::RenderResult begin_render_result(BL::RenderEngine &b_engine,
309                                             int x,
310                                             int y,
311                                             int w,
312                                             int h,
313                                             const char *layername,
314                                             const char *viewname)
315 {
316   return b_engine.begin_result(x, y, w, h, layername, viewname);
317 }
318
319 static void end_render_result(BL::RenderEngine &b_engine,
320                               BL::RenderResult &b_rr,
321                               bool cancel,
322                               bool highlight,
323                               bool do_merge_results)
324 {
325   b_engine.end_result(b_rr, (int)cancel, (int)highlight, (int)do_merge_results);
326 }
327
328 void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
329                                                  bool do_update_only,
330                                                  bool highlight)
331 {
332   int x = rtile.x - session->tile_manager.params.full_x;
333   int y = rtile.y - session->tile_manager.params.full_y;
334   int w = rtile.w;
335   int h = rtile.h;
336
337   /* get render result */
338   BL::RenderResult b_rr = begin_render_result(
339       b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
340
341   /* can happen if the intersected rectangle gives 0 width or height */
342   if (b_rr.ptr.data == NULL) {
343     return;
344   }
345
346   BL::RenderResult::layers_iterator b_single_rlay;
347   b_rr.layers.begin(b_single_rlay);
348
349   /* layer will be missing if it was disabled in the UI */
350   if (b_single_rlay == b_rr.layers.end())
351     return;
352
353   BL::RenderLayer b_rlay = *b_single_rlay;
354
355   if (do_update_only) {
356     /* Sample would be zero at initial tile update, which is only needed
357      * to tag tile form blender side as IN PROGRESS for proper highlight
358      * no buffers should be sent to blender yet. For denoise we also
359      * keep showing the noisy buffers until denoise is done. */
360     bool merge = (rtile.sample != 0) && (rtile.task != RenderTile::DENOISE);
361
362     if (merge) {
363       update_render_result(b_rr, b_rlay, rtile);
364     }
365
366     end_render_result(b_engine, b_rr, true, highlight, merge);
367   }
368   else {
369     /* Write final render result. */
370     write_render_result(b_rr, b_rlay, rtile);
371     end_render_result(b_engine, b_rr, false, false, true);
372   }
373 }
374
375 void BlenderSession::write_render_tile(RenderTile &rtile)
376 {
377   do_write_update_render_tile(rtile, false, false);
378 }
379
380 void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
381 {
382   /* use final write for preview renders, otherwise render result wouldn't be
383    * be updated in blender side
384    * would need to be investigated a bit further, but for now shall be fine
385    */
386   if (!b_engine.is_preview())
387     do_write_update_render_tile(rtile, true, highlight);
388   else
389     do_write_update_render_tile(rtile, false, false);
390 }
391
392 static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
393 {
394   string identifier = string_printf("%08x", util_murmur_hash3(name.c_str(), name.length(), 0));
395   string prefix = "cryptomatte/" + identifier.substr(0, 7) + "/";
396
397   render_add_metadata(b_rr, prefix + "name", name);
398   render_add_metadata(b_rr, prefix + "hash", "MurmurHash3_32");
399   render_add_metadata(b_rr, prefix + "conversion", "uint32_to_float32");
400   render_add_metadata(b_rr, prefix + "manifest", manifest);
401 }
402
403 void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_layer_name)
404 {
405   BL::RenderResult b_rr = b_engine.get_result();
406   string prefix = "cycles." + view_layer_name + ".";
407
408   /* Configured number of samples for the view layer. */
409   b_rr.stamp_data_add_field((prefix + "samples").c_str(),
410                             to_string(session->params.samples).c_str());
411
412   /* Store ranged samples information. */
413   if (session->tile_manager.range_num_samples != -1) {
414     b_rr.stamp_data_add_field((prefix + "range_start_sample").c_str(),
415                               to_string(session->tile_manager.range_start_sample).c_str());
416     b_rr.stamp_data_add_field((prefix + "range_num_samples").c_str(),
417                               to_string(session->tile_manager.range_num_samples).c_str());
418   }
419
420   /* Write cryptomatte metadata. */
421   if (scene->film->cryptomatte_passes & CRYPT_OBJECT) {
422     add_cryptomatte_layer(b_rr,
423                           view_layer_name + ".CryptoObject",
424                           scene->object_manager->get_cryptomatte_objects(scene));
425   }
426   if (scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
427     add_cryptomatte_layer(b_rr,
428                           view_layer_name + ".CryptoMaterial",
429                           scene->shader_manager->get_cryptomatte_materials(scene));
430   }
431   if (scene->film->cryptomatte_passes & CRYPT_ASSET) {
432     add_cryptomatte_layer(b_rr,
433                           view_layer_name + ".CryptoAsset",
434                           scene->object_manager->get_cryptomatte_assets(scene));
435   }
436
437   /* Store synchronization and bare-render times. */
438   double total_time, render_time;
439   session->progress.get_time(total_time, render_time);
440   b_rr.stamp_data_add_field((prefix + "total_time").c_str(),
441                             time_human_readable_from_seconds(total_time).c_str());
442   b_rr.stamp_data_add_field((prefix + "render_time").c_str(),
443                             time_human_readable_from_seconds(render_time).c_str());
444   b_rr.stamp_data_add_field((prefix + "synchronization_time").c_str(),
445                             time_human_readable_from_seconds(total_time - render_time).c_str());
446 }
447
448 void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
449 {
450   b_depsgraph = b_depsgraph_;
451
452   /* set callback to write out render results */
453   session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
454   session->update_render_tile_cb = function_bind(
455       &BlenderSession::update_render_tile, this, _1, _2);
456
457   /* get buffer parameters */
458   SessionParams session_params = BlenderSync::get_session_params(
459       b_engine, b_userpref, b_scene, background);
460   BufferParams buffer_params = BlenderSync::get_buffer_params(
461       b_render, b_v3d, b_rv3d, scene->camera, width, height);
462
463   /* render each layer */
464   BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
465
466   /* temporary render result to find needed passes and views */
467   BL::RenderResult b_rr = begin_render_result(
468       b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
469   BL::RenderResult::layers_iterator b_single_rlay;
470   b_rr.layers.begin(b_single_rlay);
471   BL::RenderLayer b_rlay = *b_single_rlay;
472   b_rlay_name = b_view_layer.name();
473
474   /* add passes */
475   vector<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer);
476   buffer_params.passes = passes;
477
478   PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
479   bool full_denoising = get_boolean(crl, "use_denoising");
480   bool write_denoising_passes = get_boolean(crl, "denoising_store_passes");
481
482   bool run_denoising = full_denoising || write_denoising_passes;
483
484   session->tile_manager.schedule_denoising = run_denoising;
485   buffer_params.denoising_data_pass = run_denoising;
486   buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
487   buffer_params.denoising_prefiltered_pass = write_denoising_passes;
488
489   session->params.run_denoising = run_denoising;
490   session->params.full_denoising = full_denoising;
491   session->params.write_denoising_passes = write_denoising_passes;
492   session->params.denoising.radius = get_int(crl, "denoising_radius");
493   session->params.denoising.strength = get_float(crl, "denoising_strength");
494   session->params.denoising.feature_strength = get_float(crl, "denoising_feature_strength");
495   session->params.denoising.relative_pca = get_boolean(crl, "denoising_relative_pca");
496
497   scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
498   scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
499   scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass;
500
501   scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
502   scene->film->tag_passes_update(scene, passes);
503   scene->film->tag_update(scene);
504   scene->integrator->tag_update(scene);
505
506   BL::RenderResult::views_iterator b_view_iter;
507
508   int num_views = 0;
509   for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
510     num_views++;
511   }
512
513   int view_index = 0;
514   for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end();
515        ++b_view_iter, ++view_index) {
516     b_rview_name = b_view_iter->name();
517
518     /* set the current view */
519     b_engine.active_view_set(b_rview_name.c_str());
520
521     /* update scene */
522     BL::Object b_camera_override(b_engine.camera_override());
523     sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
524     sync->sync_data(
525         b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
526     builtin_images_load();
527
528     /* Attempt to free all data which is held by Blender side, since at this
529      * point we knwo that we've got everything to render current view layer.
530      */
531     /* At the moment we only free if we are not doing multi-view (or if we are rendering the last view).
532      * See T58142/D4239 for discussion.
533      */
534     if (view_index == num_views - 1) {
535       free_blender_memory_if_possible();
536     }
537
538     /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
539     if (view_index != 0) {
540       scene->integrator->seed += hash_int_2d(scene->integrator->seed,
541                                              hash_int(view_index * 0xdeadbeef));
542       scene->integrator->tag_update(scene);
543     }
544
545     /* Update number of samples per layer. */
546     int samples = sync->get_layer_samples();
547     bool bound_samples = sync->get_layer_bound_samples();
548     int effective_layer_samples;
549
550     if (samples != 0 && (!bound_samples || (samples < session_params.samples)))
551       effective_layer_samples = samples;
552     else
553       effective_layer_samples = session_params.samples;
554
555     /* Update tile manager if we're doing resumable render. */
556     update_resumable_tile_manager(effective_layer_samples);
557
558     /* Update session itself. */
559     session->reset(buffer_params, effective_layer_samples);
560
561     /* render */
562     session->start();
563     session->wait();
564
565     if (!b_engine.is_preview() && background && print_render_stats) {
566       RenderStats stats;
567       session->collect_statistics(&stats);
568       printf("Render statistics:\n%s\n", stats.full_report().c_str());
569     }
570
571     if (session->progress.get_cancel())
572       break;
573   }
574
575   /* add metadata */
576   stamp_view_layer_metadata(scene, b_rlay_name);
577
578   /* free result without merging */
579   end_render_result(b_engine, b_rr, true, true, false);
580
581   double total_time, render_time;
582   session->progress.get_time(total_time, render_time);
583   VLOG(1) << "Total render time: " << total_time;
584   VLOG(1) << "Render time (without synchronization): " << render_time;
585
586   /* clear callback */
587   session->write_render_tile_cb = function_null;
588   session->update_render_tile_cb = function_null;
589
590   /* TODO: find a way to clear this data for persistent data render */
591 #if 0
592   /* free all memory used (host and device), so we wouldn't leave render
593    * engine with extra memory allocated
594    */
595
596   session->device_free();
597
598   delete sync;
599   sync = NULL;
600 #endif
601 }
602
603 static void populate_bake_data(BakeData *data,
604                                const int object_id,
605                                BL::BakePixel &pixel_array,
606                                const int num_pixels)
607 {
608   BL::BakePixel bp = pixel_array;
609
610   int i;
611   for (i = 0; i < num_pixels; i++) {
612     if (bp.object_id() == object_id) {
613       data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
614     }
615     else {
616       data->set_null(i);
617     }
618     bp = bp.next();
619   }
620 }
621
622 static int bake_pass_filter_get(const int pass_filter)
623 {
624   int flag = BAKE_FILTER_NONE;
625
626   if ((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0)
627     flag |= BAKE_FILTER_DIRECT;
628   if ((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0)
629     flag |= BAKE_FILTER_INDIRECT;
630   if ((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0)
631     flag |= BAKE_FILTER_COLOR;
632
633   if ((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0)
634     flag |= BAKE_FILTER_DIFFUSE;
635   if ((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0)
636     flag |= BAKE_FILTER_GLOSSY;
637   if ((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0)
638     flag |= BAKE_FILTER_TRANSMISSION;
639   if ((pass_filter & BL::BakeSettings::pass_filter_SUBSURFACE) != 0)
640     flag |= BAKE_FILTER_SUBSURFACE;
641
642   if ((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0)
643     flag |= BAKE_FILTER_EMISSION;
644   if ((pass_filter & BL::BakeSettings::pass_filter_AO) != 0)
645     flag |= BAKE_FILTER_AO;
646
647   return flag;
648 }
649
650 void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
651                           BL::Object &b_object,
652                           const string &pass_type,
653                           const int pass_filter,
654                           const int object_id,
655                           BL::BakePixel &pixel_array,
656                           const size_t num_pixels,
657                           const int /*depth*/,
658                           float result[])
659 {
660   b_depsgraph = b_depsgraph_;
661
662   ShaderEvalType shader_type = get_shader_type(pass_type);
663
664   /* Set baking flag in advance, so kernel loading can check if we need
665    * any baking capabilities.
666    */
667   scene->bake_manager->set_baking(true);
668
669   /* ensure kernels are loaded before we do any scene updates */
670   session->load_kernels();
671
672   if (shader_type == SHADER_EVAL_UV) {
673     /* force UV to be available */
674     Pass::add(PASS_UV, scene->film->passes);
675   }
676
677   int bake_pass_filter = bake_pass_filter_get(pass_filter);
678   bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
679
680   /* force use_light_pass to be true if we bake more than just colors */
681   if (bake_pass_filter & ~BAKE_FILTER_COLOR) {
682     Pass::add(PASS_LIGHT, scene->film->passes);
683   }
684
685   /* create device and update scene */
686   scene->film->tag_update(scene);
687   scene->integrator->tag_update(scene);
688
689   if (!session->progress.get_cancel()) {
690     /* update scene */
691     BL::Object b_camera_override(b_engine.camera_override());
692     sync->sync_camera(b_render, b_camera_override, width, height, "");
693     sync->sync_data(
694         b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
695     builtin_images_load();
696   }
697
698   BakeData *bake_data = NULL;
699
700   if (!session->progress.get_cancel()) {
701     /* get buffer parameters */
702     SessionParams session_params = BlenderSync::get_session_params(
703         b_engine, b_userpref, b_scene, background);
704     BufferParams buffer_params = BlenderSync::get_buffer_params(
705         b_render, b_v3d, b_rv3d, scene->camera, width, height);
706
707     scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
708
709     /* set number of samples */
710     session->tile_manager.set_samples(session_params.samples);
711     session->reset(buffer_params, session_params.samples);
712     session->update_scene();
713
714     /* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
715     size_t object_index = OBJECT_NONE;
716     int tri_offset = 0;
717
718     for (size_t i = 0; i < scene->objects.size(); i++) {
719       if (strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
720         object_index = i;
721         tri_offset = scene->objects[i]->mesh->tri_offset;
722         break;
723       }
724     }
725
726     /* Object might have been disabled for rendering or excluded in some
727      * other way, in that case Blender will report a warning afterwards. */
728     if (object_index != OBJECT_NONE) {
729       int object = object_index;
730
731       bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
732       populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
733     }
734
735     /* set number of samples */
736     session->tile_manager.set_samples(session_params.samples);
737     session->reset(buffer_params, session_params.samples);
738     session->update_scene();
739
740     session->progress.set_update_callback(
741         function_bind(&BlenderSession::update_bake_progress, this));
742   }
743
744   /* Perform bake. Check cancel to avoid crash with incomplete scene data. */
745   if (!session->progress.get_cancel() && bake_data) {
746     scene->bake_manager->bake(scene->device,
747                               &scene->dscene,
748                               scene,
749                               session->progress,
750                               shader_type,
751                               bake_pass_filter,
752                               bake_data,
753                               result);
754   }
755
756   /* free all memory used (host and device), so we wouldn't leave render
757    * engine with extra memory allocated
758    */
759
760   session->device_free();
761
762   delete sync;
763   sync = NULL;
764 }
765
766 void BlenderSession::do_write_update_render_result(BL::RenderResult &b_rr,
767                                                    BL::RenderLayer &b_rlay,
768                                                    RenderTile &rtile,
769                                                    bool do_update_only)
770 {
771   RenderBuffers *buffers = rtile.buffers;
772
773   /* copy data from device */
774   if (!buffers->copy_from_device())
775     return;
776
777   float exposure = scene->film->exposure;
778
779   vector<float> pixels(rtile.w * rtile.h * 4);
780
781   /* Adjust absolute sample number to the range. */
782   int sample = rtile.sample;
783   const int range_start_sample = session->tile_manager.range_start_sample;
784   if (range_start_sample != -1) {
785     sample -= range_start_sample;
786   }
787
788   if (!do_update_only) {
789     /* copy each pass */
790     BL::RenderLayer::passes_iterator b_iter;
791
792     for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
793       BL::RenderPass b_pass(*b_iter);
794
795       /* find matching pass type */
796       PassType pass_type = BlenderSync::get_pass_type(b_pass);
797       int components = b_pass.channels();
798
799       bool read = false;
800       if (pass_type != PASS_NONE) {
801         /* copy pixels */
802         read = buffers->get_pass_rect(
803             pass_type, exposure, sample, components, &pixels[0], b_pass.name());
804       }
805       else {
806         int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
807         if (denoising_offset >= 0) {
808           read = buffers->get_denoising_pass_rect(
809               denoising_offset, exposure, sample, components, &pixels[0]);
810         }
811       }
812
813       if (!read) {
814         memset(&pixels[0], 0, pixels.size() * sizeof(float));
815       }
816
817       b_pass.rect(&pixels[0]);
818     }
819   }
820   else {
821     /* copy combined pass */
822     BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
823     if (buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0], "Combined"))
824       b_combined_pass.rect(&pixels[0]);
825   }
826
827   /* tag result as updated */
828   b_engine.update_result(b_rr);
829 }
830
831 void BlenderSession::write_render_result(BL::RenderResult &b_rr,
832                                          BL::RenderLayer &b_rlay,
833                                          RenderTile &rtile)
834 {
835   do_write_update_render_result(b_rr, b_rlay, rtile, false);
836 }
837
838 void BlenderSession::update_render_result(BL::RenderResult &b_rr,
839                                           BL::RenderLayer &b_rlay,
840                                           RenderTile &rtile)
841 {
842   do_write_update_render_result(b_rr, b_rlay, rtile, true);
843 }
844
845 void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
846 {
847   /* only used for viewport render */
848   if (!b_v3d)
849     return;
850
851   /* on session/scene parameter changes, we recreate session entirely */
852   SessionParams session_params = BlenderSync::get_session_params(
853       b_engine, b_userpref, b_scene, background);
854   SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
855   bool session_pause = BlenderSync::get_session_pause(b_scene, background);
856
857   if (session->params.modified(session_params) || scene->params.modified(scene_params)) {
858     free_session();
859     create_session();
860     return;
861   }
862
863   /* increase samples, but never decrease */
864   session->set_samples(session_params.samples);
865   session->set_pause(session_pause);
866
867   /* copy recalc flags, outside of mutex so we can decide to do the real
868    * synchronization at a later time to not block on running updates */
869   sync->sync_recalc(b_depsgraph_);
870
871   /* don't do synchronization if on pause */
872   if (session_pause) {
873     tag_update();
874     return;
875   }
876
877   /* try to acquire mutex. if we don't want to or can't, come back later */
878   if (!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
879     tag_update();
880     return;
881   }
882
883   /* data and camera synchronize */
884   b_depsgraph = b_depsgraph_;
885
886   BL::Object b_camera_override(b_engine.camera_override());
887   sync->sync_data(
888       b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
889
890   if (b_rv3d)
891     sync->sync_view(b_v3d, b_rv3d, width, height);
892   else
893     sync->sync_camera(b_render, b_camera_override, width, height, "");
894
895   builtin_images_load();
896
897   /* unlock */
898   session->scene->mutex.unlock();
899
900   /* reset if needed */
901   if (scene->need_reset()) {
902     BufferParams buffer_params = BlenderSync::get_buffer_params(
903         b_render, b_v3d, b_rv3d, scene->camera, width, height);
904     session->reset(buffer_params, session_params.samples);
905
906     /* reset time */
907     start_resize_time = 0.0;
908   }
909
910   /* Start rendering thread, if it's not running already. Do this
911    * after all scene data has been synced at least once. */
912   session->start();
913 }
914
915 bool BlenderSession::draw(int w, int h)
916 {
917   /* pause in redraw in case update is not being called due to final render */
918   session->set_pause(BlenderSync::get_session_pause(b_scene, background));
919
920   /* before drawing, we verify camera and viewport size changes, because
921    * we do not get update callbacks for those, we must detect them here */
922   if (session->ready_to_reset()) {
923     bool reset = false;
924
925     /* if dimensions changed, reset */
926     if (width != w || height != h) {
927       if (start_resize_time == 0.0) {
928         /* don't react immediately to resizes to avoid flickery resizing
929          * of the viewport, and some window managers changing the window
930          * size temporarily on unminimize */
931         start_resize_time = time_dt();
932         tag_redraw();
933       }
934       else if (time_dt() - start_resize_time < 0.2) {
935         tag_redraw();
936       }
937       else {
938         width = w;
939         height = h;
940         reset = true;
941       }
942     }
943
944     /* try to acquire mutex. if we can't, come back later */
945     if (!session->scene->mutex.try_lock()) {
946       tag_update();
947     }
948     else {
949       /* update camera from 3d view */
950
951       sync->sync_view(b_v3d, b_rv3d, width, height);
952
953       if (scene->camera->need_update)
954         reset = true;
955
956       session->scene->mutex.unlock();
957     }
958
959     /* reset if requested */
960     if (reset) {
961       SessionParams session_params = BlenderSync::get_session_params(
962           b_engine, b_userpref, b_scene, background);
963       BufferParams buffer_params = BlenderSync::get_buffer_params(
964           b_render, b_v3d, b_rv3d, scene->camera, width, height);
965       bool session_pause = BlenderSync::get_session_pause(b_scene, background);
966
967       if (session_pause == false) {
968         session->reset(buffer_params, session_params.samples);
969         start_resize_time = 0.0;
970       }
971     }
972   }
973   else {
974     tag_update();
975   }
976
977   /* update status and progress for 3d view draw */
978   update_status_progress();
979
980   /* draw */
981   BufferParams buffer_params = BlenderSync::get_buffer_params(
982       b_render, b_v3d, b_rv3d, scene->camera, width, height);
983   DeviceDrawParams draw_params;
984
985   if (session->params.display_buffer_linear) {
986     draw_params.bind_display_space_shader_cb = function_bind(
987         &BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
988     draw_params.unbind_display_space_shader_cb = function_bind(
989         &BL::RenderEngine::unbind_display_space_shader, &b_engine);
990   }
991
992   return !session->draw(buffer_params, draw_params);
993 }
994
995 void BlenderSession::get_status(string &status, string &substatus)
996 {
997   session->progress.get_status(status, substatus);
998 }
999
1000 void BlenderSession::get_kernel_status(string &kernel_status)
1001 {
1002   session->progress.get_kernel_status(kernel_status);
1003 }
1004
1005 void BlenderSession::get_progress(float &progress, double &total_time, double &render_time)
1006 {
1007   session->progress.get_time(total_time, render_time);
1008   progress = session->progress.get_progress();
1009 }
1010
1011 void BlenderSession::update_bake_progress()
1012 {
1013   float progress = session->progress.get_progress();
1014
1015   if (progress != last_progress) {
1016     b_engine.update_progress(progress);
1017     last_progress = progress;
1018   }
1019 }
1020
1021 void BlenderSession::update_status_progress()
1022 {
1023   string timestatus, status, substatus, kernel_status;
1024   string scene_status = "";
1025   float progress;
1026   double total_time, remaining_time = 0, render_time;
1027   float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
1028   float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
1029
1030   get_status(status, substatus);
1031   get_kernel_status(kernel_status);
1032   get_progress(progress, total_time, render_time);
1033
1034   if (progress > 0)
1035     remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
1036
1037   if (background) {
1038     scene_status += " | " + scene->name;
1039     if (b_rlay_name != "")
1040       scene_status += ", " + b_rlay_name;
1041
1042     if (b_rview_name != "")
1043       scene_status += ", " + b_rview_name;
1044
1045     if (remaining_time > 0) {
1046       timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | ";
1047     }
1048
1049     timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
1050
1051     if (status.size() > 0)
1052       status = " | " + status;
1053     if (substatus.size() > 0)
1054       status += " | " + substatus;
1055     if (kernel_status.size() > 0)
1056       status += " | " + kernel_status;
1057   }
1058
1059   double current_time = time_dt();
1060   /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date.
1061    * For headless rendering, only report when something significant changes to keep the console output readable. */
1062   if (status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
1063     b_engine.update_stats("", (timestatus + scene_status + status).c_str());
1064     b_engine.update_memory_stats(mem_used, mem_peak);
1065     last_status = status;
1066     last_status_time = current_time;
1067   }
1068   if (progress != last_progress) {
1069     b_engine.update_progress(progress);
1070     last_progress = progress;
1071   }
1072
1073   if (session->progress.get_error()) {
1074     string error = session->progress.get_error_message();
1075     if (error != last_error) {
1076       /* TODO(sergey): Currently C++ RNA API doesn't let us to
1077        * use mnemonic name for the variable. Would be nice to
1078        * have this figured out.
1079        *
1080        * For until then, 1 << 5 means RPT_ERROR.
1081        */
1082       b_engine.report(1 << 5, error.c_str());
1083       b_engine.error_set(error.c_str());
1084       last_error = error;
1085     }
1086   }
1087 }
1088
1089 void BlenderSession::tag_update()
1090 {
1091   /* tell blender that we want to get another update callback */
1092   b_engine.tag_update();
1093 }
1094
1095 void BlenderSession::tag_redraw()
1096 {
1097   if (background) {
1098     /* update stats and progress, only for background here because
1099      * in 3d view we do it in draw for thread safety reasons */
1100     update_status_progress();
1101
1102     /* offline render, redraw if timeout passed */
1103     if (time_dt() - last_redraw_time > 1.0) {
1104       b_engine.tag_redraw();
1105       last_redraw_time = time_dt();
1106     }
1107   }
1108   else {
1109     /* tell blender that we want to redraw */
1110     b_engine.tag_redraw();
1111   }
1112 }
1113
1114 void BlenderSession::test_cancel()
1115 {
1116   /* test if we need to cancel rendering */
1117   if (background)
1118     if (b_engine.test_break())
1119       session->progress.set_cancel("Cancelled");
1120 }
1121
1122 /* builtin image file name is actually an image datablock name with
1123  * absolute sequence frame number concatenated via '@' character
1124  *
1125  * this function splits frame from builtin name
1126  */
1127 int BlenderSession::builtin_image_frame(const string &builtin_name)
1128 {
1129   int last = builtin_name.find_last_of('@');
1130   return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
1131 }
1132
1133 void BlenderSession::builtin_image_info(const string &builtin_name,
1134                                         void *builtin_data,
1135                                         ImageMetaData &metadata)
1136 {
1137   /* empty image */
1138   metadata.width = 1;
1139   metadata.height = 1;
1140
1141   if (!builtin_data)
1142     return;
1143
1144   /* recover ID pointer */
1145   PointerRNA ptr;
1146   RNA_id_pointer_create((ID *)builtin_data, &ptr);
1147   BL::ID b_id(ptr);
1148
1149   if (b_id.is_a(&RNA_Image)) {
1150     /* image data */
1151     BL::Image b_image(b_id);
1152
1153     metadata.builtin_free_cache = !b_image.has_data();
1154     metadata.is_float = b_image.is_float();
1155     metadata.width = b_image.size()[0];
1156     metadata.height = b_image.size()[1];
1157     metadata.depth = 1;
1158     metadata.channels = b_image.channels();
1159   }
1160   else if (b_id.is_a(&RNA_Object)) {
1161     /* smoke volume data */
1162     BL::Object b_ob(b_id);
1163     BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
1164
1165     metadata.is_float = true;
1166     metadata.depth = 1;
1167     metadata.channels = 1;
1168
1169     if (!b_domain)
1170       return;
1171
1172     if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
1173         builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
1174         builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
1175         builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
1176       metadata.channels = 1;
1177     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
1178       metadata.channels = 4;
1179     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
1180       metadata.channels = 3;
1181     else
1182       return;
1183
1184     int3 resolution = get_int3(b_domain.domain_resolution());
1185     int amplify = (b_domain.use_high_resolution()) ? b_domain.amplify() + 1 : 1;
1186
1187     /* Velocity and heat data is always low-resolution. */
1188     if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
1189         builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
1190       amplify = 1;
1191     }
1192
1193     metadata.width = resolution.x * amplify;
1194     metadata.height = resolution.y * amplify;
1195     metadata.depth = resolution.z * amplify;
1196   }
1197   else {
1198     /* TODO(sergey): Check we're indeed in shader node tree. */
1199     PointerRNA ptr;
1200     RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
1201     BL::Node b_node(ptr);
1202     if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
1203       BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
1204       metadata.channels = 4;
1205       metadata.width = b_point_density_node.resolution();
1206       metadata.height = metadata.width;
1207       metadata.depth = metadata.width;
1208       metadata.is_float = true;
1209     }
1210   }
1211 }
1212
1213 bool BlenderSession::builtin_image_pixels(const string &builtin_name,
1214                                           void *builtin_data,
1215                                           unsigned char *pixels,
1216                                           const size_t pixels_size,
1217                                           const bool free_cache)
1218 {
1219   if (!builtin_data) {
1220     return false;
1221   }
1222
1223   const int frame = builtin_image_frame(builtin_name);
1224
1225   PointerRNA ptr;
1226   RNA_id_pointer_create((ID *)builtin_data, &ptr);
1227   BL::Image b_image(ptr);
1228
1229   const int width = b_image.size()[0];
1230   const int height = b_image.size()[1];
1231   const int channels = b_image.channels();
1232
1233   unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame);
1234   const size_t num_pixels = ((size_t)width) * height;
1235
1236   if (image_pixels && num_pixels * channels == pixels_size) {
1237     memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
1238   }
1239   else {
1240     if (channels == 1) {
1241       memset(pixels, 0, pixels_size * sizeof(unsigned char));
1242     }
1243     else {
1244       const size_t num_pixels_safe = pixels_size / channels;
1245       unsigned char *cp = pixels;
1246       for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
1247         cp[0] = 255;
1248         cp[1] = 0;
1249         cp[2] = 255;
1250         if (channels == 4) {
1251           cp[3] = 255;
1252         }
1253       }
1254     }
1255   }
1256
1257   if (image_pixels) {
1258     MEM_freeN(image_pixels);
1259   }
1260
1261   /* Free image buffers to save memory during render. */
1262   if (free_cache) {
1263     b_image.buffers_free();
1264   }
1265
1266   /* Premultiply, byte images are always straight for Blender. */
1267   unsigned char *cp = pixels;
1268   for (size_t i = 0; i < num_pixels; i++, cp += channels) {
1269     cp[0] = (cp[0] * cp[3]) >> 8;
1270     cp[1] = (cp[1] * cp[3]) >> 8;
1271     cp[2] = (cp[2] * cp[3]) >> 8;
1272   }
1273   return true;
1274 }
1275
1276 bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
1277                                                 void *builtin_data,
1278                                                 float *pixels,
1279                                                 const size_t pixels_size,
1280                                                 const bool free_cache)
1281 {
1282   if (!builtin_data) {
1283     return false;
1284   }
1285
1286   PointerRNA ptr;
1287   RNA_id_pointer_create((ID *)builtin_data, &ptr);
1288   BL::ID b_id(ptr);
1289
1290   if (b_id.is_a(&RNA_Image)) {
1291     /* image data */
1292     BL::Image b_image(b_id);
1293     int frame = builtin_image_frame(builtin_name);
1294
1295     const int width = b_image.size()[0];
1296     const int height = b_image.size()[1];
1297     const int channels = b_image.channels();
1298
1299     float *image_pixels;
1300     image_pixels = image_get_float_pixels_for_frame(b_image, frame);
1301     const size_t num_pixels = ((size_t)width) * height;
1302
1303     if (image_pixels && num_pixels * channels == pixels_size) {
1304       memcpy(pixels, image_pixels, pixels_size * sizeof(float));
1305     }
1306     else {
1307       if (channels == 1) {
1308         memset(pixels, 0, num_pixels * sizeof(float));
1309       }
1310       else {
1311         const size_t num_pixels_safe = pixels_size / channels;
1312         float *fp = pixels;
1313         for (int i = 0; i < num_pixels_safe; i++, fp += channels) {
1314           fp[0] = 1.0f;
1315           fp[1] = 0.0f;
1316           fp[2] = 1.0f;
1317           if (channels == 4) {
1318             fp[3] = 1.0f;
1319           }
1320         }
1321       }
1322     }
1323
1324     if (image_pixels) {
1325       MEM_freeN(image_pixels);
1326     }
1327
1328     /* Free image buffers to save memory during render. */
1329     if (free_cache) {
1330       b_image.buffers_free();
1331     }
1332
1333     return true;
1334   }
1335   else if (b_id.is_a(&RNA_Object)) {
1336     /* smoke volume data */
1337     BL::Object b_ob(b_id);
1338     BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
1339
1340     if (!b_domain) {
1341       return false;
1342     }
1343
1344     int3 resolution = get_int3(b_domain.domain_resolution());
1345     int length, amplify = (b_domain.use_high_resolution()) ? b_domain.amplify() + 1 : 1;
1346
1347     /* Velocity and heat data is always low-resolution. */
1348     if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
1349         builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
1350       amplify = 1;
1351     }
1352
1353     const int width = resolution.x * amplify;
1354     const int height = resolution.y * amplify;
1355     const int depth = resolution.z * amplify;
1356     const size_t num_pixels = ((size_t)width) * height * depth;
1357
1358     if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
1359       SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
1360       if (length == num_pixels) {
1361         SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels);
1362         return true;
1363       }
1364     }
1365     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
1366       /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
1367        * as 1500..3000 K with the first part faded to zero density */
1368       SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
1369       if (length == num_pixels) {
1370         SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
1371         return true;
1372       }
1373     }
1374     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
1375       /* the RGB is "premultiplied" by density for better interpolation results */
1376       SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
1377       if (length == num_pixels * 4) {
1378         SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels);
1379         return true;
1380       }
1381     }
1382     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
1383       SmokeDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
1384       if (length == num_pixels * 3) {
1385         SmokeDomainSettings_velocity_grid_get(&b_domain.ptr, pixels);
1386         return true;
1387       }
1388     }
1389     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
1390       SmokeDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
1391       if (length == num_pixels) {
1392         SmokeDomainSettings_heat_grid_get(&b_domain.ptr, pixels);
1393         return true;
1394       }
1395     }
1396     else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
1397       SmokeDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
1398       if (length == num_pixels) {
1399         SmokeDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
1400         return true;
1401       }
1402     }
1403     else {
1404       fprintf(
1405           stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str());
1406       pixels[0] = 0.0f;
1407       return false;
1408     }
1409
1410     fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
1411   }
1412   else {
1413     /* We originally were passing view_layer here but in reality we need a
1414      * a depsgraph to pass to the RE_point_density_minmax() function.
1415      */
1416     /* TODO(sergey): Check we're indeed in shader node tree. */
1417     PointerRNA ptr;
1418     RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
1419     BL::Node b_node(ptr);
1420     if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
1421       BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
1422       int length;
1423       b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
1424     }
1425   }
1426
1427   return false;
1428 }
1429
1430 void BlenderSession::builtin_images_load()
1431 {
1432   /* Force builtin images to be loaded along with Blender data sync. This
1433    * is needed because we may be reading from depsgraph evaluated data which
1434    * can be freed by Blender before Cycles reads it. */
1435   ImageManager *manager = session->scene->image_manager;
1436   Device *device = session->device;
1437   manager->device_load_builtin(device, session->scene, session->progress);
1438 }
1439
1440 void BlenderSession::update_resumable_tile_manager(int num_samples)
1441 {
1442   const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
1443             current_resumable_chunk = BlenderSession::current_resumable_chunk;
1444   if (num_resumable_chunks == 0) {
1445     return;
1446   }
1447
1448   if (num_resumable_chunks > num_samples) {
1449     fprintf(stderr,
1450             "Cycles warning: more sample chunks (%d) than samples (%d), "
1451             "this will cause some samples to be included in multiple chunks.\n",
1452             num_resumable_chunks,
1453             num_samples);
1454   }
1455
1456   const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
1457
1458   float range_start_sample, range_num_samples;
1459   if (current_resumable_chunk != 0) {
1460     /* Single chunk rendering. */
1461     range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
1462     range_num_samples = num_samples_per_chunk;
1463   }
1464   else {
1465     /* Ranged-chunks. */
1466     const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
1467     range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
1468     range_num_samples = num_chunks * num_samples_per_chunk;
1469   }
1470
1471   /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
1472    * to allow for many small chunks. */
1473   int rounded_range_start_sample = (int)floor(range_start_sample + 0.5f);
1474   int rounded_range_num_samples = max((int)floor(range_num_samples + 0.5f), 1);
1475
1476   /* Make sure we don't overshoot. */
1477   if (rounded_range_start_sample + rounded_range_num_samples > num_samples) {
1478     rounded_range_num_samples = num_samples - rounded_range_num_samples;
1479   }
1480
1481   VLOG(1) << "Samples range start is " << range_start_sample << ", "
1482           << "number of samples to render is " << range_num_samples;
1483
1484   scene->integrator->start_sample = rounded_range_start_sample;
1485   scene->integrator->tag_update(scene);
1486
1487   session->tile_manager.range_start_sample = rounded_range_start_sample;
1488   session->tile_manager.range_num_samples = rounded_range_num_samples;
1489 }
1490
1491 void BlenderSession::free_blender_memory_if_possible()
1492 {
1493   if (!background) {
1494     /* During interactive render we can not free anything: attempts to save
1495      * memory would cause things to be allocated and evaluated for every
1496      * updated sample.
1497      */
1498     return;
1499   }
1500   b_engine.free_blender_memory();
1501 }
1502
1503 CCL_NAMESPACE_END