Blender  V2.93
blender_session.cpp
Go to the documentation of this file.
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 
45 #include "blender/blender_sync.h"
46 #include "blender/blender_util.h"
47 
49 
51 bool BlenderSession::headless = false;
57 
59  BL::Preferences &b_userpref,
60  BL::BlendData &b_data,
61  bool preview_osl)
62  : session(NULL),
63  scene(NULL),
64  sync(NULL),
65  b_engine(b_engine),
66  b_userpref(b_userpref),
67  b_data(b_data),
68  b_render(b_engine.render()),
69  b_depsgraph(PointerRNA_NULL),
70  b_scene(PointerRNA_NULL),
71  b_v3d(PointerRNA_NULL),
72  b_rv3d(PointerRNA_NULL),
73  width(0),
74  height(0),
75  preview_osl(preview_osl),
76  python_thread_state(NULL)
77 {
78  /* offline render */
79  background = true;
80  last_redraw_time = 0.0;
81  start_resize_time = 0.0;
82  last_status_time = 0.0;
83 }
84 
86  BL::Preferences &b_userpref,
87  BL::BlendData &b_data,
88  BL::SpaceView3D &b_v3d,
89  BL::RegionView3D &b_rv3d,
90  int width,
91  int height)
92  : session(NULL),
93  scene(NULL),
94  sync(NULL),
95  b_engine(b_engine),
96  b_userpref(b_userpref),
97  b_data(b_data),
98  b_render(b_engine.render()),
99  b_depsgraph(PointerRNA_NULL),
100  b_scene(PointerRNA_NULL),
101  b_v3d(b_v3d),
102  b_rv3d(b_rv3d),
103  width(width),
104  height(height),
105  preview_osl(false),
106  python_thread_state(NULL)
107 {
108  /* 3d view render */
109  background = false;
110  last_redraw_time = 0.0;
111  start_resize_time = 0.0;
112  last_status_time = 0.0;
113 }
114 
116 {
117  free_session();
118 }
119 
121 {
125  bool session_pause = BlenderSync::get_session_pause(b_scene, background);
126 
127  /* reset status/progress */
128  last_status = "";
129  last_error = "";
130  last_progress = -1.0f;
131  start_resize_time = 0.0;
132 
133  /* create session */
134  session = new Session(session_params);
135  session->scene = scene;
138  session->set_pause(session_pause);
139 
140  /* create scene */
141  scene = new Scene(scene_params, session->device);
142  scene->name = b_scene.name();
143 
144  session->scene = scene;
145 
146  /* create sync */
148  BL::Object b_camera_override(b_engine.camera_override());
149  if (b_v3d) {
151  }
152  else {
153  sync->sync_camera(b_render, b_camera_override, width, height, "");
154  }
155 
156  /* set buffer parameters */
158  b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
159  session->reset(buffer_params, session_params.samples);
160 
161  b_engine.use_highlight_tiles(session_params.progressive_refine == false);
162 
163  update_resumable_tile_manager(session_params.samples);
164 }
165 
166 void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
167 {
168  /* Update data, scene and depsgraph pointers. These can change after undo. */
169  this->b_data = b_data;
170  this->b_depsgraph = b_depsgraph;
171  this->b_scene = b_depsgraph.scene_eval();
172  if (sync) {
173  sync->reset(this->b_data, this->b_scene);
174  }
175 
176  if (preview_osl) {
177  PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
178  RNA_boolean_set(&cscene, "shading_system", preview_osl);
179  }
180 
181  if (b_v3d) {
182  this->b_render = b_scene.render();
183  }
184  else {
185  this->b_render = b_engine.render();
188  }
189 
190  bool is_new_session = (session == NULL);
191  if (is_new_session) {
192  /* Initialize session and remember it was just created so not to
193  * re-create it below.
194  */
195  create_session();
196  }
197 
198  if (b_v3d) {
199  /* NOTE: We need to create session, but all the code from below
200  * will make viewport render to stuck on initialization.
201  */
202  return;
203  }
204 
208 
209  if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
210  !this->b_render.use_persistent_data()) {
211  /* if scene or session parameters changed, it's easier to simply re-create
212  * them rather than trying to distinguish which settings need to be updated
213  */
214  if (!is_new_session) {
215  free_session();
216  create_session();
217  }
218  return;
219  }
220 
222 
224 
225  /* peak memory usage should show current render peak, not peak for all renders
226  * made by this render session
227  */
229 
230  if (is_new_session) {
231  /* Sync object should be re-created for new scene. */
232  delete sync;
234  }
235  else {
236  /* Sync recalculations to do just the required updates. */
238  }
239 
240  BL::Object b_camera_override(b_engine.camera_override());
241  sync->sync_camera(b_render, b_camera_override, width, height, "");
242 
243  BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
244  BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
246  b_null_space_view3d,
247  b_null_region_view3d,
248  scene->camera,
249  width,
250  height,
251  session_params.denoising.use);
252  session->reset(buffer_params, session_params.samples);
253 
254  b_engine.use_highlight_tiles(session_params.progressive_refine == false);
255 
256  /* reset time */
257  start_resize_time = 0.0;
258 }
259 
261 {
262  session->cancel();
263 
264  delete sync;
265  delete session;
266 }
267 
268 static ShaderEvalType get_shader_type(const string &pass_type)
269 {
270  const char *shader_type = pass_type.c_str();
271 
272  /* data passes */
273  if (strcmp(shader_type, "NORMAL") == 0)
274  return SHADER_EVAL_NORMAL;
275  else if (strcmp(shader_type, "UV") == 0)
276  return SHADER_EVAL_UV;
277  else if (strcmp(shader_type, "ROUGHNESS") == 0)
278  return SHADER_EVAL_ROUGHNESS;
279  else if (strcmp(shader_type, "DIFFUSE_COLOR") == 0)
281  else if (strcmp(shader_type, "GLOSSY_COLOR") == 0)
283  else if (strcmp(shader_type, "TRANSMISSION_COLOR") == 0)
285  else if (strcmp(shader_type, "EMIT") == 0)
286  return SHADER_EVAL_EMISSION;
287 
288  /* light passes */
289  else if (strcmp(shader_type, "AO") == 0)
290  return SHADER_EVAL_AO;
291  else if (strcmp(shader_type, "COMBINED") == 0)
292  return SHADER_EVAL_COMBINED;
293  else if (strcmp(shader_type, "SHADOW") == 0)
294  return SHADER_EVAL_SHADOW;
295  else if (strcmp(shader_type, "DIFFUSE") == 0)
296  return SHADER_EVAL_DIFFUSE;
297  else if (strcmp(shader_type, "GLOSSY") == 0)
298  return SHADER_EVAL_GLOSSY;
299  else if (strcmp(shader_type, "TRANSMISSION") == 0)
301 
302  /* extra */
303  else if (strcmp(shader_type, "ENVIRONMENT") == 0)
305 
306  else
307  return SHADER_EVAL_BAKE;
308 }
309 
311  int x,
312  int y,
313  int w,
314  int h,
315  const char *layername,
316  const char *viewname)
317 {
318  return b_engine.begin_result(x, y, w, h, layername, viewname);
319 }
320 
321 static void end_render_result(BL::RenderEngine &b_engine,
322  BL::RenderResult &b_rr,
323  bool cancel,
324  bool highlight,
325  bool do_merge_results)
326 {
327  b_engine.end_result(b_rr, (int)cancel, (int)highlight, (int)do_merge_results);
328 }
329 
331  bool do_update_only,
332  bool do_read_only,
333  bool highlight)
334 {
335  int x = rtile.x - session->tile_manager.params.full_x;
336  int y = rtile.y - session->tile_manager.params.full_y;
337  int w = rtile.w;
338  int h = rtile.h;
339 
340  /* get render result */
342  b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
343 
344  /* can happen if the intersected rectangle gives 0 width or height */
345  if (b_rr.ptr.data == NULL) {
346  return;
347  }
348 
349  BL::RenderResult::layers_iterator b_single_rlay;
350  b_rr.layers.begin(b_single_rlay);
351 
352  /* layer will be missing if it was disabled in the UI */
353  if (b_single_rlay == b_rr.layers.end())
354  return;
355 
356  BL::RenderLayer b_rlay = *b_single_rlay;
357 
358  if (do_read_only) {
359  /* copy each pass */
360  for (BL::RenderPass &b_pass : b_rlay.passes) {
361  /* find matching pass type */
362  PassType pass_type = BlenderSync::get_pass_type(b_pass);
363  int components = b_pass.channels();
364 
365  rtile.buffers->set_pass_rect(
366  pass_type, components, (float *)b_pass.rect(), rtile.num_samples);
367  }
368 
369  end_render_result(b_engine, b_rr, false, false, false);
370  }
371  else if (do_update_only) {
372  /* Sample would be zero at initial tile update, which is only needed
373  * to tag tile form blender side as IN PROGRESS for proper highlight
374  * no buffers should be sent to blender yet. For denoise we also
375  * keep showing the noisy buffers until denoise is done. */
376  bool merge = (rtile.sample != 0) && (rtile.task != RenderTile::DENOISE);
377 
378  if (merge) {
379  update_render_result(b_rlay, rtile);
380  }
381 
382  end_render_result(b_engine, b_rr, true, highlight, merge);
383  }
384  else {
385  /* Write final render result. */
386  write_render_result(b_rlay, rtile);
387  end_render_result(b_engine, b_rr, false, false, true);
388  }
389 }
390 
392 {
393  do_write_update_render_tile(rtile, false, true, false);
394 }
395 
397 {
398  do_write_update_render_tile(rtile, false, false, false);
399 }
400 
401 void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
402 {
403  /* use final write for preview renders, otherwise render result wouldn't be
404  * be updated in blender side
405  * would need to be investigated a bit further, but for now shall be fine
406  */
407  if (!b_engine.is_preview())
408  do_write_update_render_tile(rtile, true, false, highlight);
409  else
410  do_write_update_render_tile(rtile, false, false, false);
411 }
412 
413 static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
414 {
415  string identifier = string_printf("%08x", util_murmur_hash3(name.c_str(), name.length(), 0));
416  string prefix = "cryptomatte/" + identifier.substr(0, 7) + "/";
417 
418  render_add_metadata(b_rr, prefix + "name", name);
419  render_add_metadata(b_rr, prefix + "hash", "MurmurHash3_32");
420  render_add_metadata(b_rr, prefix + "conversion", "uint32_to_float32");
421  render_add_metadata(b_rr, prefix + "manifest", manifest);
422 }
423 
424 void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_layer_name)
425 {
426  BL::RenderResult b_rr = b_engine.get_result();
427  string prefix = "cycles." + view_layer_name + ".";
428 
429  /* Configured number of samples for the view layer. */
430  b_rr.stamp_data_add_field((prefix + "samples").c_str(),
431  to_string(session->params.samples).c_str());
432 
433  /* Store ranged samples information. */
435  b_rr.stamp_data_add_field((prefix + "range_start_sample").c_str(),
437  b_rr.stamp_data_add_field((prefix + "range_num_samples").c_str(),
439  }
440 
441  /* Write cryptomatte metadata. */
442  if (scene->film->get_cryptomatte_passes() & CRYPT_OBJECT) {
444  view_layer_name + ".CryptoObject",
446  }
447  if (scene->film->get_cryptomatte_passes() & CRYPT_MATERIAL) {
449  view_layer_name + ".CryptoMaterial",
451  }
452  if (scene->film->get_cryptomatte_passes() & CRYPT_ASSET) {
454  view_layer_name + ".CryptoAsset",
456  }
457 
458  /* Store synchronization and bare-render times. */
459  double total_time, render_time;
460  session->progress.get_time(total_time, render_time);
461  b_rr.stamp_data_add_field((prefix + "total_time").c_str(),
462  time_human_readable_from_seconds(total_time).c_str());
463  b_rr.stamp_data_add_field((prefix + "render_time").c_str(),
464  time_human_readable_from_seconds(render_time).c_str());
465  b_rr.stamp_data_add_field((prefix + "synchronization_time").c_str(),
466  time_human_readable_from_seconds(total_time - render_time).c_str());
467 }
468 
470 {
471  b_depsgraph = b_depsgraph_;
472 
473  if (session->progress.get_cancel()) {
475  return;
476  }
477 
478  /* set callback to write out render results */
481  &BlenderSession::update_render_tile, this, _1, _2);
482 
483  BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
484 
485  /* get buffer parameters */
487  b_engine, b_userpref, b_scene, background, b_view_layer);
489  b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
490 
491  /* temporary render result to find needed passes and views */
493  b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
494  BL::RenderResult::layers_iterator b_single_rlay;
495  b_rr.layers.begin(b_single_rlay);
496  BL::RenderLayer b_rlay = *b_single_rlay;
497  b_rlay_name = b_view_layer.name();
498 
499  /* Update denoising parameters. */
500  session->set_denoising(session_params.denoising);
501 
502  /* Compute render passes and film settings. */
504  b_scene, b_rlay, b_view_layer, session_params.adaptive_sampling, session_params.denoising);
505 
506  /* Set buffer params, using film settings from sync_render_passes. */
507  buffer_params.passes = passes;
508  buffer_params.denoising_data_pass = scene->film->get_denoising_data_pass();
509  buffer_params.denoising_clean_pass = scene->film->get_denoising_clean_pass();
510  buffer_params.denoising_prefiltered_pass = scene->film->get_denoising_prefiltered_pass();
511 
512  BL::RenderResult::views_iterator b_view_iter;
513 
514  int num_views = 0;
515  for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
516  num_views++;
517  }
518 
519  int view_index = 0;
520  for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end();
521  ++b_view_iter, ++view_index) {
522  b_rview_name = b_view_iter->name();
523 
524  /* set the current view */
525  b_engine.active_view_set(b_rview_name.c_str());
526 
527  /* Force update in this case, since the camera transform on each frame changes
528  * in different views. This could be optimized by somehow storing the animated
529  * camera transforms separate from the fixed stereo transform. */
530  if ((scene->need_motion() != Scene::MOTION_NONE) && view_index > 0) {
531  sync->tag_update();
532  }
533 
534  /* update scene */
535  BL::Object b_camera_override(b_engine.camera_override());
536  sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
537  sync->sync_data(
538  b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
540 
541  /* Attempt to free all data which is held by Blender side, since at this
542  * point we know that we've got everything to render current view layer.
543  */
544  /* At the moment we only free if we are not doing multi-view
545  * (or if we are rendering the last view). See T58142/D4239 for discussion.
546  */
547  if (view_index == num_views - 1) {
549  }
550 
551  /* Make sure all views have different noise patterns. - hardcoded value just to make it random
552  */
553  if (view_index != 0) {
554  int seed = scene->integrator->get_seed();
555  seed += hash_uint2(seed, hash_uint2(view_index * 0xdeadbeef, 0));
556  scene->integrator->set_seed(seed);
557  }
558 
559  /* Update number of samples per layer. */
560  int samples = sync->get_layer_samples();
561  bool bound_samples = sync->get_layer_bound_samples();
562  int effective_layer_samples;
563 
564  if (samples != 0 && (!bound_samples || (samples < session_params.samples)))
565  effective_layer_samples = samples;
566  else
567  effective_layer_samples = session_params.samples;
568 
569  /* Update tile manager if we're doing resumable render. */
570  update_resumable_tile_manager(effective_layer_samples);
571 
572  /* Update session itself. */
573  session->reset(buffer_params, effective_layer_samples);
574 
575  /* render */
576  if (!b_engine.is_preview() && background && print_render_stats) {
578  }
579 
580  session->start();
581  session->wait();
582 
583  if (!b_engine.is_preview() && background && print_render_stats) {
584  RenderStats stats;
585  session->collect_statistics(&stats);
586  printf("Render statistics:\n%s\n", stats.full_report().c_str());
587  }
588 
589  if (session->progress.get_cancel())
590  break;
591  }
592 
593  /* add metadata */
595 
596  /* free result without merging */
597  end_render_result(b_engine, b_rr, true, true, false);
598 
599  double total_time, render_time;
600  session->progress.get_time(total_time, render_time);
601  VLOG(1) << "Total render time: " << total_time;
602  VLOG(1) << "Render time (without synchronization): " << render_time;
603 
604  /* clear callback */
607 }
608 
609 static int bake_pass_filter_get(const int pass_filter)
610 {
611  int flag = BAKE_FILTER_NONE;
612 
613  if ((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0)
614  flag |= BAKE_FILTER_DIRECT;
615  if ((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0)
616  flag |= BAKE_FILTER_INDIRECT;
617  if ((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0)
618  flag |= BAKE_FILTER_COLOR;
619 
620  if ((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0)
621  flag |= BAKE_FILTER_DIFFUSE;
622  if ((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0)
623  flag |= BAKE_FILTER_GLOSSY;
624  if ((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0)
625  flag |= BAKE_FILTER_TRANSMISSION;
626 
627  if ((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0)
628  flag |= BAKE_FILTER_EMISSION;
629  if ((pass_filter & BL::BakeSettings::pass_filter_AO) != 0)
630  flag |= BAKE_FILTER_AO;
631 
632  return flag;
633 }
634 
636  BL::Object &b_object,
637  const string &pass_type,
638  const int pass_filter,
639  const int bake_width,
640  const int bake_height)
641 {
642  b_depsgraph = b_depsgraph_;
643 
644  ShaderEvalType shader_type = get_shader_type(pass_type);
645  int bake_pass_filter = bake_pass_filter_get(pass_filter);
646 
647  /* Initialize bake manager, before we load the baking kernels. */
648  scene->bake_manager->set(scene, b_object.name(), shader_type, bake_pass_filter);
649 
650  /* Passes are identified by name, so in order to return the combined pass we need to set the
651  * name. */
652  Pass::add(PASS_COMBINED, scene->passes, "Combined");
653 
656 
657  if (!session->progress.get_cancel()) {
658  /* Sync scene. */
659  BL::Object b_camera_override(b_engine.camera_override());
660  sync->sync_camera(b_render, b_camera_override, width, height, "");
661  sync->sync_data(
662  b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
664  }
665 
666  /* Object might have been disabled for rendering or excluded in some
667  * other way, in that case Blender will report a warning afterwards. */
668  bool object_found = false;
669  foreach (Object *ob, scene->objects) {
670  if (ob->name == b_object.name()) {
671  object_found = true;
672  break;
673  }
674  }
675 
676  if (object_found && !session->progress.get_cancel()) {
677  /* Get session and buffer parameters. */
680  session_params.progressive_refine = false;
681 
682  BufferParams buffer_params;
683  buffer_params.width = bake_width;
684  buffer_params.height = bake_height;
685  buffer_params.passes = scene->passes;
686 
687  /* Update session. */
688  session->tile_manager.set_samples(session_params.samples);
689  session->reset(buffer_params, session_params.samples);
690 
693  }
694 
695  /* Perform bake. Check cancel to avoid crash with incomplete scene data. */
696  if (object_found && !session->progress.get_cancel()) {
697  session->start();
698  session->wait();
699  }
700 
703 }
704 
706  RenderTile &rtile,
707  bool do_update_only)
708 {
709  RenderBuffers *buffers = rtile.buffers;
710 
711  /* copy data from device */
712  if (!buffers->copy_from_device())
713  return;
714 
715  float exposure = scene->film->get_exposure();
716 
717  vector<float> pixels(rtile.w * rtile.h * 4);
718 
719  /* Adjust absolute sample number to the range. */
720  int sample = rtile.sample;
721  const int range_start_sample = session->tile_manager.range_start_sample;
722  if (range_start_sample != -1) {
723  sample -= range_start_sample;
724  }
725 
726  if (!do_update_only) {
727  /* copy each pass */
728  for (BL::RenderPass &b_pass : b_rlay.passes) {
729  int components = b_pass.channels();
730 
731  /* Copy pixels from regular render passes. */
732  bool read = buffers->get_pass_rect(b_pass.name(), exposure, sample, components, &pixels[0]);
733 
734  /* If denoising pass, */
735  if (!read) {
736  int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
737  if (denoising_offset >= 0) {
738  read = buffers->get_denoising_pass_rect(
739  denoising_offset, exposure, sample, components, &pixels[0]);
740  }
741  }
742 
743  if (!read) {
744  memset(&pixels[0], 0, pixels.size() * sizeof(float));
745  }
746 
747  b_pass.rect(&pixels[0]);
748  }
749  }
750  else {
751  /* copy combined pass */
752  BL::RenderPass b_combined_pass(b_rlay.passes.find_by_name("Combined", b_rview_name.c_str()));
753  if (buffers->get_pass_rect("Combined", exposure, sample, 4, &pixels[0]))
754  b_combined_pass.rect(&pixels[0]);
755  }
756 }
757 
759 {
760  do_write_update_render_result(b_rlay, rtile, false);
761 }
762 
764 {
765  do_write_update_render_result(b_rlay, rtile, true);
766 }
767 
769 {
770  /* only used for viewport render */
771  if (!b_v3d)
772  return;
773 
774  /* on session/scene parameter changes, we recreate session entirely */
778  bool session_pause = BlenderSync::get_session_pause(b_scene, background);
779 
780  if (session->params.modified(session_params) || scene->params.modified(scene_params)) {
781  free_session();
782  create_session();
783  }
784 
785  /* increase samples, but never decrease */
786  session->set_samples(session_params.samples);
788  session->set_pause(session_pause);
789 
790  /* copy recalc flags, outside of mutex so we can decide to do the real
791  * synchronization at a later time to not block on running updates */
792  sync->sync_recalc(b_depsgraph_, b_v3d);
793 
794  /* don't do synchronization if on pause */
795  if (session_pause) {
796  tag_update();
797  return;
798  }
799 
800  /* try to acquire mutex. if we don't want to or can't, come back later */
801  if (!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
802  tag_update();
803  return;
804  }
805 
806  /* data and camera synchronize */
807  b_depsgraph = b_depsgraph_;
808 
809  BL::Object b_camera_override(b_engine.camera_override());
810  sync->sync_data(
811  b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
812 
813  if (b_rv3d)
815  else
816  sync->sync_camera(b_render, b_camera_override, width, height, "");
817 
818  /* get buffer parameters */
820  b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
821 
822  if (!buffer_params.denoising_data_pass) {
823  session_params.denoising.use = false;
824  }
825 
826  session->set_denoising(session_params.denoising);
827 
828  /* Update film if denoising data was enabled or disabled. */
829  scene->film->set_denoising_data_pass(buffer_params.denoising_data_pass);
830 
831  /* reset if needed */
832  if (scene->need_reset()) {
833  session->reset(buffer_params, session_params.samples);
834 
835  /* After session reset, so device is not accessing image data anymore. */
837 
838  /* reset time */
839  start_resize_time = 0.0;
840  }
841 
842  /* unlock */
843  session->scene->mutex.unlock();
844 
845  /* Start rendering thread, if it's not running already. Do this
846  * after all scene data has been synced at least once. */
847  session->start();
848 }
849 
850 bool BlenderSession::draw(int w, int h)
851 {
852  /* pause in redraw in case update is not being called due to final render */
854 
855  /* before drawing, we verify camera and viewport size changes, because
856  * we do not get update callbacks for those, we must detect them here */
857  if (session->ready_to_reset()) {
858  bool reset = false;
859 
860  /* if dimensions changed, reset */
861  if (width != w || height != h) {
862  if (start_resize_time == 0.0) {
863  /* don't react immediately to resizes to avoid flickery resizing
864  * of the viewport, and some window managers changing the window
865  * size temporarily on unminimize */
867  tag_redraw();
868  }
869  else if (time_dt() - start_resize_time < 0.2) {
870  tag_redraw();
871  }
872  else {
873  width = w;
874  height = h;
875  reset = true;
876  }
877  }
878 
879  /* try to acquire mutex. if we can't, come back later */
880  if (!session->scene->mutex.try_lock()) {
881  tag_update();
882  }
883  else {
884  /* update camera from 3d view */
885 
887 
888  if (scene->camera->is_modified())
889  reset = true;
890 
891  session->scene->mutex.unlock();
892  }
893 
894  /* reset if requested */
895  if (reset) {
899  b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
900  bool session_pause = BlenderSync::get_session_pause(b_scene, background);
901 
902  if (session_pause == false) {
903  session->reset(buffer_params, session_params.samples);
904  start_resize_time = 0.0;
905  }
906  }
907  }
908  else {
909  tag_update();
910  }
911 
912  /* update status and progress for 3d view draw */
914 
915  /* draw */
918  DeviceDrawParams draw_params;
919 
922  &BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
924  &BL::RenderEngine::unbind_display_space_shader, &b_engine);
925  }
926 
927  return !session->draw(buffer_params, draw_params);
928 }
929 
930 void BlenderSession::get_status(string &status, string &substatus)
931 {
932  session->progress.get_status(status, substatus);
933 }
934 
935 void BlenderSession::get_kernel_status(string &kernel_status)
936 {
937  session->progress.get_kernel_status(kernel_status);
938 }
939 
940 void BlenderSession::get_progress(float &progress, double &total_time, double &render_time)
941 {
942  session->progress.get_time(total_time, render_time);
943  progress = session->progress.get_progress();
944 }
945 
947 {
948  float progress = session->progress.get_progress();
949 
950  if (progress != last_progress) {
951  b_engine.update_progress(progress);
952  last_progress = progress;
953  }
954 }
955 
957 {
958  string timestatus, status, substatus, kernel_status;
959  string scene_status = "";
960  float progress;
961  double total_time, remaining_time = 0, render_time;
962  float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
963  float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
964 
965  get_status(status, substatus);
966  get_kernel_status(kernel_status);
967  get_progress(progress, total_time, render_time);
968 
969  if (progress > 0)
970  remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
971 
972  if (background) {
973  if (scene)
974  scene_status += " | " + scene->name;
975  if (b_rlay_name != "")
976  scene_status += ", " + b_rlay_name;
977 
978  if (b_rview_name != "")
979  scene_status += ", " + b_rview_name;
980 
981  if (remaining_time > 0) {
982  timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | ";
983  }
984 
985  timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
986 
987  if (status.size() > 0)
988  status = " | " + status;
989  if (substatus.size() > 0)
990  status += " | " + substatus;
991  if (kernel_status.size() > 0)
992  status += " | " + kernel_status;
993  }
994 
995  double current_time = time_dt();
996  /* When rendering in a window, redraw the status at least once per second to keep the elapsed and
997  * remaining time up-to-date. For headless rendering, only report when something significant
998  * changes to keep the console output readable. */
999  if (status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
1000  b_engine.update_stats("", (timestatus + scene_status + status).c_str());
1001  b_engine.update_memory_stats(mem_used, mem_peak);
1002  last_status = status;
1003  last_status_time = current_time;
1004  }
1005  if (progress != last_progress) {
1006  b_engine.update_progress(progress);
1007  last_progress = progress;
1008  }
1009 
1010  if (session->progress.get_error()) {
1012  if (error != last_error) {
1013  /* TODO(sergey): Currently C++ RNA API doesn't let us to
1014  * use mnemonic name for the variable. Would be nice to
1015  * have this figured out.
1016  *
1017  * For until then, 1 << 5 means RPT_ERROR.
1018  */
1019  b_engine.report(1 << 5, error.c_str());
1020  b_engine.error_set(error.c_str());
1021  last_error = error;
1022  }
1023  }
1024 }
1025 
1027 {
1028  /* tell blender that we want to get another update callback */
1029  b_engine.tag_update();
1030 }
1031 
1033 {
1034  if (background) {
1035  /* update stats and progress, only for background here because
1036  * in 3d view we do it in draw for thread safety reasons */
1038 
1039  /* offline render, redraw if timeout passed */
1040  if (time_dt() - last_redraw_time > 1.0) {
1041  b_engine.tag_redraw();
1043  }
1044  }
1045  else {
1046  /* tell blender that we want to redraw */
1047  b_engine.tag_redraw();
1048  }
1049 }
1050 
1052 {
1053  /* test if we need to cancel rendering */
1054  if (background)
1055  if (b_engine.test_break())
1056  session->progress.set_cancel("Cancelled");
1057 }
1058 
1060 {
1063  if (num_resumable_chunks == 0) {
1064  return;
1065  }
1066 
1067  if (num_resumable_chunks > num_samples) {
1068  fprintf(stderr,
1069  "Cycles warning: more sample chunks (%d) than samples (%d), "
1070  "this will cause some samples to be included in multiple chunks.\n",
1072  num_samples);
1073  }
1074 
1075  const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
1076 
1077  float range_start_sample, range_num_samples;
1078  if (current_resumable_chunk != 0) {
1079  /* Single chunk rendering. */
1080  range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
1081  range_num_samples = num_samples_per_chunk;
1082  }
1083  else {
1084  /* Ranged-chunks. */
1085  const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
1086  range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
1087  range_num_samples = num_chunks * num_samples_per_chunk;
1088  }
1089 
1090  /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
1091  * to allow for many small chunks. */
1092  int rounded_range_start_sample = (int)floorf(range_start_sample + 0.5f);
1093  int rounded_range_num_samples = max((int)floorf(range_num_samples + 0.5f), 1);
1094 
1095  /* Make sure we don't overshoot. */
1096  if (rounded_range_start_sample + rounded_range_num_samples > num_samples) {
1097  rounded_range_num_samples = num_samples - rounded_range_num_samples;
1098  }
1099 
1100  VLOG(1) << "Samples range start is " << range_start_sample << ", "
1101  << "number of samples to render is " << range_num_samples;
1102 
1103  scene->integrator->set_start_sample(rounded_range_start_sample);
1104 
1105  session->tile_manager.range_start_sample = rounded_range_start_sample;
1106  session->tile_manager.range_num_samples = rounded_range_num_samples;
1107 }
1108 
1110 {
1111  if (!background) {
1112  /* During interactive render we can not free anything: attempts to save
1113  * memory would cause things to be allocated and evaluated for every
1114  * updated sample.
1115  */
1116  return;
1117  }
1118  b_engine.free_blender_memory();
1119 }
1120 
typedef float(TangentPoint)[2]
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
struct ViewLayer ViewLayer
struct Object Object
struct Scene Scene
struct RegionView3D RegionView3D
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
struct RenderEngine RenderEngine
struct RenderLayer RenderLayer
struct RenderResult RenderResult
struct RenderPass RenderPass
static ShaderEvalType get_shader_type(const string &pass_type)
static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
static void end_render_result(BL::RenderEngine &b_engine, BL::RenderResult &b_rr, bool cancel, bool highlight, bool do_merge_results)
static int bake_pass_filter_get(const int pass_filter)
static BL::RenderResult begin_render_result(BL::RenderEngine &b_engine, int x, int y, int w, int h, const char *layername, const char *viewname)
static int render_resolution_x(BL::RenderSettings &b_render)
Definition: blender_util.h:227
static int render_resolution_y(BL::RenderSettings &b_render)
Definition: blender_util.h:232
static void render_add_metadata(BL::RenderResult &b_rr, string name, string value)
Definition: blender_util.h:270
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static unsigned long seed
Definition: btSoftBody.h:39
void reset()
clear internal cached data and reset random seed
void set(Scene *scene, const std::string &object_name, ShaderEvalType type, int pass_filter)
Definition: bake.cpp:93
void stamp_view_layer_metadata(Scene *scene, const string &view_layer_name)
void get_progress(float &progress, double &total_time, double &render_time)
BL::RenderSettings b_render
static bool headless
void get_kernel_status(string &kernel_status)
static bool print_render_stats
BL::RegionView3D b_rv3d
double start_resize_time
BL::RenderEngine b_engine
void synchronize(BL::Depsgraph &b_depsgraph)
static int end_resumable_chunk
void do_write_update_render_tile(RenderTile &rtile, bool do_update_only, bool do_read_only, bool highlight)
void write_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile)
void builtin_images_load()
void update_status_progress()
void * python_thread_state
void free_blender_memory_if_possible()
static int start_resumable_chunk
BL::Preferences b_userpref
void read_render_tile(RenderTile &rtile)
BlenderSync * sync
static int current_resumable_chunk
void reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
void bake(BL::Depsgraph &b_depsgrah, BL::Object &b_object, const string &pass_type, const int custom_flag, const int bake_width, const int bake_height)
BL::BlendData b_data
bool draw(int w, int h)
void update_render_tile(RenderTile &rtile, bool highlight)
Session * session
void render(BL::Depsgraph &b_depsgraph)
void write_render_tile(RenderTile &rtile)
BL::SpaceView3D b_v3d
void update_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile)
BlenderSession(BL::RenderEngine &b_engine, BL::Preferences &b_userpref, BL::BlendData &b_data, bool preview_osl)
void do_write_update_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile, bool do_update_only)
static int num_resumable_chunks
double last_redraw_time
void get_status(string &status, string &substatus)
BL::Depsgraph b_depsgraph
static DeviceTypeMask device_override
void update_resumable_tile_manager(int num_samples)
static BufferParams get_buffer_params(BL::RenderSettings &b_render, BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, Camera *cam, int width, int height, const bool use_denoiser)
static bool get_session_pause(BL::Scene &b_scene, bool background)
static SessionParams get_session_params(BL::RenderEngine &b_engine, BL::Preferences &b_userpref, BL::Scene &b_scene, bool background, BL::ViewLayer b_view_layer=BL::ViewLayer(PointerRNA_NULL))
void sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
void tag_update()
static SceneParams get_scene_params(BL::Scene &b_scene, bool background)
void sync_camera(BL::RenderSettings &b_render, BL::Object &b_override, int width, int height, const char *viewname)
int get_layer_bound_samples()
Definition: blender_sync.h:95
vector< Pass > sync_render_passes(BL::Scene &b_scene, BL::RenderLayer &b_render_layer, BL::ViewLayer &b_view_layer, bool adaptive_sampling, const DenoiseParams &denoising)
void sync_view(BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height)
static int get_denoising_pass(BL::RenderPass &b_pass)
static PassType get_pass_type(BL::RenderPass &b_pass)
void sync_data(BL::RenderSettings &b_render, BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, BL::Object &b_override, int width, int height, void **python_thread_state)
void reset(BL::BlendData &b_data, BL::Scene &b_scene)
int get_layer_samples()
Definition: blender_sync.h:91
int width
Definition: buffers.h:43
int full_x
Definition: buffers.h:47
vector< Pass > passes
Definition: buffers.h:53
int height
Definition: buffers.h:44
bool denoising_prefiltered_pass
Definition: buffers.h:60
bool denoising_clean_pass
Definition: buffers.h:56
int full_y
Definition: buffers.h:48
bool denoising_data_pass
Definition: buffers.h:54
string get_cryptomatte_objects(Scene *scene)
Definition: object.cpp:936
string get_cryptomatte_assets(Scene *scene)
Definition: object.cpp:953
static void add(PassType type, vector< Pass > &passes, const char *name=NULL)
Definition: film.cpp:103
void set_cancel_callback(function< void()> function)
float get_progress()
void set_cancel(const string &cancel_message_)
Definition: util_progress.h:98
void get_status(string &status_, string &substatus_)
bool get_cancel()
void get_time(double &total_time_, double &render_time_)
void reset()
Definition: util_progress.h:76
string get_error_message()
bool get_error()
void get_kernel_status(string &kernel_status_)
void set_update_callback(function< void()> function)
bool get_pass_rect(const string &name, float exposure, int sample, int components, float *pixels)
Definition: buffers.cpp:257
bool set_pass_rect(PassType type, int components, float *pixels, int samples)
Definition: buffers.cpp:463
bool get_denoising_pass_rect(int offset, float exposure, int sample, int components, float *pixels)
Definition: buffers.cpp:169
bool copy_from_device()
Definition: buffers.cpp:159
int sample
Definition: buffers.h:140
RenderBuffers * buffers
Definition: buffers.h:152
int num_samples
Definition: buffers.h:139
Task task
Definition: buffers.h:136
bool modified(const SceneParams &params)
Definition: scene.h:199
int samples
Definition: session.h:52
bool progressive_refine
Definition: session.h:48
DenoiseParams denoising
Definition: session.h:65
TileOrder tile_order
Definition: session.h:54
bool display_buffer_linear
Definition: session.h:63
bool adaptive_sampling
Definition: session.h:59
bool modified(const SessionParams &params)
Definition: session.h:104
void set_denoising_start_sample(int sample)
Definition: session.cpp:994
void collect_statistics(RenderStats *stats)
Definition: session.cpp:1301
function< void(RenderTile &, bool)> update_render_tile_cb
Definition: session.h:143
void wait()
Definition: session.cpp:1003
Device * device
Definition: session.h:132
bool draw(BufferParams &params, DeviceDrawParams &draw_params)
Definition: session.cpp:897
void set_pause(bool pause)
Definition: session.cpp:946
bool ready_to_reset()
Definition: session.cpp:154
TileManager tile_manager
Definition: session.h:138
void start()
Definition: session.cpp:128
Progress progress
Definition: session.h:136
void set_denoising(const DenoiseParams &denoising)
Definition: session.cpp:969
SessionParams params
Definition: session.h:137
function< void(RenderTile &)> write_render_tile_cb
Definition: session.h:142
void cancel()
Definition: session.cpp:135
void reset(BufferParams &params, int samples)
Definition: session.cpp:928
Scene * scene
Definition: session.h:133
Stats stats
Definition: session.h:139
void set_samples(int samples)
Definition: session.cpp:936
function< void(RenderTile &)> read_bake_tile_cb
Definition: session.h:144
string get_cryptomatte_materials(Scene *scene)
Definition: shader.cpp:774
size_t mem_used
Definition: util_stats.h:48
size_t mem_peak
Definition: util_stats.h:49
int range_start_sample
Definition: tile.h:125
int range_num_samples
Definition: tile.h:128
void set_tile_order(TileOrder tile_order_)
Definition: tile.h:114
void set_samples(int num_samples)
Definition: tile.cpp:164
BufferParams params
Definition: tile.h:69
Scene scene
#define function_bind
DeviceTypeMask
Definition: device.h:54
@ DEVICE_MASK_ALL
Definition: device.h:60
#define CCL_NAMESPACE_END
#define floorf(x)
@ CRYPT_ASSET
Definition: kernel_types.h:404
@ CRYPT_OBJECT
Definition: kernel_types.h:402
@ CRYPT_MATERIAL
Definition: kernel_types.h:403
PassType
Definition: kernel_types.h:347
@ PASS_COMBINED
Definition: kernel_types.h:351
ShaderEvalType
Definition: kernel_types.h:196
@ SHADER_EVAL_TRANSMISSION_COLOR
Definition: kernel_types.h:209
@ SHADER_EVAL_DIFFUSE
Definition: kernel_types.h:218
@ SHADER_EVAL_TRANSMISSION
Definition: kernel_types.h:220
@ SHADER_EVAL_GLOSSY
Definition: kernel_types.h:219
@ SHADER_EVAL_DIFFUSE_COLOR
Definition: kernel_types.h:207
@ SHADER_EVAL_EMISSION
Definition: kernel_types.h:210
@ SHADER_EVAL_UV
Definition: kernel_types.h:205
@ SHADER_EVAL_ROUGHNESS
Definition: kernel_types.h:206
@ SHADER_EVAL_SHADOW
Definition: kernel_types.h:217
@ SHADER_EVAL_AO
Definition: kernel_types.h:215
@ SHADER_EVAL_NORMAL
Definition: kernel_types.h:204
@ SHADER_EVAL_BAKE
Definition: kernel_types.h:200
@ SHADER_EVAL_GLOSSY_COLOR
Definition: kernel_types.h:208
@ SHADER_EVAL_ENVIRONMENT
Definition: kernel_types.h:223
@ SHADER_EVAL_COMBINED
Definition: kernel_types.h:216
@ BAKE_FILTER_EMISSION
Definition: kernel_types.h:442
@ BAKE_FILTER_TRANSMISSION
Definition: kernel_types.h:441
@ BAKE_FILTER_DIFFUSE
Definition: kernel_types.h:439
@ BAKE_FILTER_NONE
Definition: kernel_types.h:435
@ BAKE_FILTER_DIRECT
Definition: kernel_types.h:436
@ BAKE_FILTER_INDIRECT
Definition: kernel_types.h:437
@ BAKE_FILTER_AO
Definition: kernel_types.h:443
@ BAKE_FILTER_COLOR
Definition: kernel_types.h:438
@ BAKE_FILTER_GLOSSY
Definition: kernel_types.h:440
static void error(const char *str)
Definition: meshlaplacian.c:65
static void sample(SocketReader *reader, int x, int y, float color[4])
std::string to_string(const T &n)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6562
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:71
function< void()> unbind_display_space_shader_cb
Definition: device.h:290
function< void()> bind_display_space_shader_cb
Definition: device.h:289
bool is_modified()
Definition: node.cpp:781
ustring name
Definition: node.h:174
string full_report()
Definition: stats.cpp:332
BakeManager * bake_manager
Definition: scene.h:249
Film * film
Definition: scene.h:229
string name
Definition: scene.h:222
SceneParams params
Definition: scene.h:264
vector< Pass > passes
Definition: scene.h:239
void enable_update_stats()
Definition: scene.cpp:446
vector< Object * > objects
Definition: scene.h:234
MotionType need_motion()
Definition: scene.cpp:358
ObjectManager * object_manager
Definition: scene.h:247
@ MOTION_NONE
Definition: scene.h:280
ShaderManager * shader_manager
Definition: scene.h:245
Integrator * integrator
Definition: scene.h:231
thread_mutex mutex
Definition: scene.h:267
struct Object * camera
bool need_reset()
Definition: scene.cpp:410
float max
__forceinline BoundBox merge(const BoundBox &bbox, const float3 &pt)
#define function_null
Definition: util_function.h:25
ccl_device_inline uint hash_uint2(uint kx, uint ky)
Definition: util_hash.h:83
#define VLOG(severity)
Definition: util_logging.h:50
uint32_t util_murmur_hash3(const void *key, int len, uint32_t seed)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: util_string.cpp:32
string time_human_readable_from_seconds(const double seconds)
Definition: util_time.cpp:78
CCL_NAMESPACE_BEGIN double time_dt()
Definition: util_time.cpp:48