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