Blender V4.3
scene.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <stdlib.h>
6
7#include "bvh/bvh.h"
8#include "device/device.h"
9#include "scene/alembic.h"
10#include "scene/background.h"
11#include "scene/bake.h"
12#include "scene/camera.h"
13#include "scene/curves.h"
14#include "scene/devicescene.h"
15#include "scene/film.h"
16#include "scene/integrator.h"
17#include "scene/light.h"
18#include "scene/mesh.h"
19#include "scene/object.h"
20#include "scene/osl.h"
21#include "scene/particles.h"
22#include "scene/pointcloud.h"
23#include "scene/procedural.h"
24#include "scene/scene.h"
25#include "scene/shader.h"
26#include "scene/svm.h"
27#include "scene/tables.h"
28#include "scene/volume.h"
29#include "session/session.h"
30
31#include "util/foreach.h"
33#include "util/log.h"
34#include "util/progress.h"
35
37
38Scene::Scene(const SceneParams &params_, Device *device)
39 : name("Scene"),
40 bvh(NULL),
41 default_surface(NULL),
42 default_volume(NULL),
43 default_light(NULL),
44 default_background(NULL),
45 default_empty(NULL),
46 device(device),
47 dscene(device),
48 params(params_),
49 update_stats(NULL),
50 kernels_loaded(false),
51 /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
52 max_closure_global(1)
53{
54 memset((void *)&dscene.data, 0, sizeof(dscene.data));
55
58
66
67 /* Create nodes after managers, since create_node() can tag the managers. */
68 camera = create_node<Camera>();
71 film = create_node<Film>();
72 background = create_node<Background>();
74
75 film->add_default(this);
77}
78
80{
81 free_memory(true);
82}
83
84void Scene::free_memory(bool final)
85{
86 delete bvh;
87 bvh = NULL;
88
89 /* The order of deletion is important to make sure data is freed based on possible dependencies
90 * as the Nodes' reference counts are decremented in the destructors:
91 *
92 * - Procedurals can create and hold pointers to any other types.
93 * - Objects can hold pointers to Geometries and ParticleSystems
94 * - Lights and Geometries can hold pointers to Shaders.
95 *
96 * Similarly, we first delete all nodes and their associated device data, and then the managers
97 * and their associated device data.
98 */
99 foreach (Procedural *p, procedurals)
100 delete p;
101 foreach (Object *o, objects)
102 delete o;
103 foreach (Geometry *g, geometry)
104 delete g;
105 foreach (ParticleSystem *p, particle_systems)
106 delete p;
107 foreach (Light *l, lights)
108 delete l;
109 foreach (Pass *p, passes)
110 delete p;
111
112 geometry.clear();
113 objects.clear();
114 lights.clear();
115 particle_systems.clear();
116 procedurals.clear();
117 passes.clear();
118
119 if (device) {
120 camera->device_free(device, &dscene, this);
121 film->device_free(device, &dscene, this);
122 background->device_free(device, &dscene);
124 }
125
126 if (final) {
127 delete camera;
128 delete dicing_camera;
129 delete film;
130 delete background;
131 delete integrator;
132 }
133
134 /* Delete Shaders after every other nodes to ensure that we do not try to decrement the reference
135 * count on some dangling pointer. */
136 foreach (Shader *s, shaders)
137 delete s;
138
139 shaders.clear();
140
141 /* Now that all nodes have been deleted, we can safely delete managers and device data. */
142 if (device) {
147
149
151
152 if (final) {
154 }
155 else {
157 }
158
160 }
161
162 if (final) {
163 delete lookup_tables;
164 delete object_manager;
165 delete geometry_manager;
166 delete shader_manager;
167 delete light_manager;
169 delete image_manager;
170 delete bake_manager;
171 delete update_stats;
172 delete procedural_manager;
173 }
174}
175
176void Scene::device_update(Device *device_, Progress &progress)
177{
178 if (!device) {
179 device = device_;
180 }
181
182 bool print_stats = need_data_update();
183
184 if (update_stats) {
186 }
187
188 scoped_callback_timer timer([this, print_stats](double time) {
189 if (update_stats) {
190 update_stats->scene.times.add_entry({"device_update", time});
191
192 if (print_stats) {
193 printf("Update statistics:\n%s\n", update_stats->full_report().c_str());
194 }
195 }
196 });
197
198 /* The order of updates is important, because there's dependencies between
199 * the different managers, using data computed by previous managers.
200 *
201 * - Image manager uploads images used by shaders.
202 * - Camera may be used for adaptive subdivision.
203 * - Displacement shader must have all shader data available.
204 * - Light manager needs lookup tables and final mesh data to compute emission CDF.
205 * - Lookup tables are done a second time to handle film tables
206 */
207
208 if (film->update_lightgroups(this)) {
209 light_manager->tag_update(this, ccl::LightManager::LIGHT_MODIFIED);
210 object_manager->tag_update(this, ccl::ObjectManager::OBJECT_MODIFIED);
211 background->tag_modified();
212 }
213 if (film->exposure_is_modified()) {
215 }
216
217 progress.set_status("Updating Shaders");
218 shader_manager->device_update(device, &dscene, this, progress);
219
220 if (progress.get_cancel() || device->have_error()) {
221 return;
222 }
223
224 procedural_manager->update(this, progress);
225
226 if (progress.get_cancel()) {
227 return;
228 }
229
230 progress.set_status("Updating Background");
231 background->device_update(device, &dscene, this);
232
233 if (progress.get_cancel() || device->have_error()) {
234 return;
235 }
236
237 progress.set_status("Updating Camera");
238 camera->device_update(device, &dscene, this);
239
240 if (progress.get_cancel() || device->have_error()) {
241 return;
242 }
243
245
246 if (progress.get_cancel() || device->have_error()) {
247 return;
248 }
249
250 progress.set_status("Updating Objects");
251 object_manager->device_update(device, &dscene, this, progress);
252
253 if (progress.get_cancel() || device->have_error()) {
254 return;
255 }
256
257 progress.set_status("Updating Particle Systems");
259
260 if (progress.get_cancel() || device->have_error()) {
261 return;
262 }
263
264 progress.set_status("Updating Meshes");
265 geometry_manager->device_update(device, &dscene, this, progress);
266
267 if (progress.get_cancel() || device->have_error()) {
268 return;
269 }
270
271 progress.set_status("Updating Objects Flags");
273
274 if (progress.get_cancel() || device->have_error()) {
275 return;
276 }
277
278 progress.set_status("Updating Primitive Offsets");
280
281 if (progress.get_cancel() || device->have_error()) {
282 return;
283 }
284
285 progress.set_status("Updating Images");
286 image_manager->device_update(device, this, progress);
287
288 if (progress.get_cancel() || device->have_error()) {
289 return;
290 }
291
292 progress.set_status("Updating Camera Volume");
293 camera->device_update_volume(device, &dscene, this);
294
295 if (progress.get_cancel() || device->have_error()) {
296 return;
297 }
298
299 progress.set_status("Updating Lookup Tables");
301
302 if (progress.get_cancel() || device->have_error()) {
303 return;
304 }
305
306 progress.set_status("Updating Lights");
307 light_manager->device_update(device, &dscene, this, progress);
308
309 if (progress.get_cancel() || device->have_error()) {
310 return;
311 }
312
313 progress.set_status("Updating Integrator");
315
316 if (progress.get_cancel() || device->have_error()) {
317 return;
318 }
319
320 progress.set_status("Updating Film");
321 film->device_update(device, &dscene, this);
322
323 if (progress.get_cancel() || device->have_error()) {
324 return;
325 }
326
327 progress.set_status("Updating Lookup Tables");
329
330 if (progress.get_cancel() || device->have_error()) {
331 return;
332 }
333
334 progress.set_status("Updating Baking");
335 bake_manager->device_update(device, &dscene, this, progress);
336
337 if (progress.get_cancel() || device->have_error()) {
338 return;
339 }
340
341 if (device->have_error() == false) {
342 dscene.data.volume_stack_size = get_volume_stack_size();
343
344 progress.set_status("Updating Device", "Writing constant memory");
345 device->const_copy_to("data", &dscene.data, sizeof(dscene.data));
346 }
347
349
350 if (print_stats) {
351 size_t mem_used = util_guarded_get_mem_used();
352 size_t mem_peak = util_guarded_get_mem_peak();
353
354 VLOG_INFO << "System memory statistics after full device sync:\n"
355 << " Usage: " << string_human_readable_number(mem_used) << " ("
356 << string_human_readable_size(mem_used) << ")\n"
357 << " Peak: " << string_human_readable_number(mem_peak) << " ("
358 << string_human_readable_size(mem_peak) << ")";
359 }
360}
361
363{
364 if (integrator->get_motion_blur()) {
365 return MOTION_BLUR;
366 }
367 else if (Pass::contains(passes, PASS_MOTION)) {
368 return MOTION_PASS;
369 }
370 else {
371 return MOTION_NONE;
372 }
373}
374
376{
378 return 2.0f;
379 }
380 else {
381 return camera->get_shuttertime();
382 }
383}
384
386{
387 if (std == ATTR_STD_UV) {
388 return Pass::contains(passes, PASS_UV);
389 }
390 else if (std == ATTR_STD_MOTION_VERTEX_POSITION) {
391 return need_motion() != MOTION_NONE;
392 }
393 else if (std == ATTR_STD_MOTION_VERTEX_NORMAL) {
394 return need_motion() == MOTION_BLUR;
395 }
396 else if (std == ATTR_STD_VOLUME_VELOCITY || std == ATTR_STD_VOLUME_VELOCITY_X ||
398 {
399 return need_motion() != MOTION_NONE;
400 }
401
402 return false;
403}
404
406{
407 for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
409 attributes.add((AttributeStandard)std);
410 }
411 }
412}
413
415{
416 return (need_reset() || film->is_modified());
417}
418
428
429bool Scene::need_reset(const bool check_camera)
430{
431 return need_data_update() || (check_camera && camera->is_modified());
432}
433
435{
436 shader_manager->reset(this);
438
439 /* ensure all objects are updated */
440 camera->tag_modified();
442 film->tag_modified();
443 background->tag_modified();
444
445 background->tag_update(this);
452}
453
455{
456 free_memory(false);
457}
458
464
466{
467 if (!update_stats) {
469 }
470}
471
473{
474 if (!need_update()) {
475 return;
476 }
477
478 thread_scoped_lock scene_lock(mutex);
479
480 /* These features are not being tweaked as often as shaders,
481 * so could be done selective magic for the viewport as well. */
482 uint kernel_features = shader_manager->get_kernel_features(this);
483
484 bool use_motion = need_motion() == Scene::MotionType::MOTION_BLUR;
485 kernel_features |= KERNEL_FEATURE_PATH_TRACING;
487 kernel_features |= KERNEL_FEATURE_HAIR_THICK;
488 }
489
490 /* Figure out whether the scene will use shader ray-trace we need at least
491 * one caustic light, one caustic caster and one caustic receiver to use
492 * and enable the MNEE code path. */
493 bool has_caustics_receiver = false;
494 bool has_caustics_caster = false;
495 bool has_caustics_light = false;
496
497 foreach (Object *object, objects) {
498 if (object->get_is_caustics_caster()) {
499 has_caustics_caster = true;
500 }
501 else if (object->get_is_caustics_receiver()) {
502 has_caustics_receiver = true;
503 }
504 Geometry *geom = object->get_geometry();
505 if (use_motion) {
506 if (object->use_motion() || geom->get_use_motion_blur()) {
507 kernel_features |= KERNEL_FEATURE_OBJECT_MOTION;
508 }
509 }
510 if (object->get_is_shadow_catcher()) {
511 kernel_features |= KERNEL_FEATURE_SHADOW_CATCHER;
512 }
513 if (geom->is_mesh()) {
514#ifdef WITH_OPENSUBDIV
515 Mesh *mesh = static_cast<Mesh *>(geom);
516 if (mesh->get_subdivision_type() != Mesh::SUBDIVISION_NONE) {
517 kernel_features |= KERNEL_FEATURE_PATCH_EVALUATION;
518 }
519#endif
520 }
521 else if (geom->is_hair()) {
522 kernel_features |= KERNEL_FEATURE_HAIR;
523 }
524 else if (geom->is_pointcloud()) {
525 kernel_features |= KERNEL_FEATURE_POINTCLOUD;
526 }
527 if (object->has_light_linking()) {
528 kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
529 }
530 if (object->has_shadow_linking()) {
531 kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
532 }
533 }
534
535 foreach (Light *light, lights) {
536 if (light->get_use_caustics()) {
537 has_caustics_light = true;
538 }
539
540 if (light->has_light_linking()) {
541 kernel_features |= KERNEL_FEATURE_LIGHT_LINKING;
542 }
543 if (light->has_shadow_linking()) {
544 kernel_features |= KERNEL_FEATURE_SHADOW_LINKING;
545 }
546 }
547
548 dscene.data.integrator.use_caustics = false;
549 if (device->info.has_mnee && has_caustics_caster && has_caustics_receiver && has_caustics_light)
550 {
551 dscene.data.integrator.use_caustics = true;
552 kernel_features |= KERNEL_FEATURE_MNEE;
553 }
554
556 kernel_features |= KERNEL_FEATURE_PATH_GUIDING;
557 }
558
559 if (bake_manager->get_baking()) {
560 kernel_features |= KERNEL_FEATURE_BAKING;
561 }
562
563 kernel_features |= film->get_kernel_features(this);
564 kernel_features |= integrator->get_kernel_features();
565
566 dscene.data.kernel_features = kernel_features;
567
568 /* Currently viewport render is faster with higher max_closures, needs investigating. */
569 const uint max_closures = (params.background) ? get_max_closure_count() : MAX_CLOSURE;
570 dscene.data.max_closures = max_closures;
571 dscene.data.max_shaders = shaders.size();
572}
573
574bool Scene::update(Progress &progress)
575{
576 if (!need_update()) {
577 return false;
578 }
579
580 /* Upload scene data to the GPU. */
581 progress.set_status("Updating Scene");
582 MEM_GUARDED_CALL(&progress, device_update, device, progress);
583
584 return true;
585}
586
587static void log_kernel_features(const uint features)
588{
589 VLOG_INFO << "Requested features:\n";
590 VLOG_INFO << "Use BSDF " << string_from_bool(features & KERNEL_FEATURE_NODE_BSDF) << "\n";
591 VLOG_INFO << "Use Emission " << string_from_bool(features & KERNEL_FEATURE_NODE_EMISSION)
592 << "\n";
593 VLOG_INFO << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_NODE_VOLUME) << "\n";
594 VLOG_INFO << "Use Bump " << string_from_bool(features & KERNEL_FEATURE_NODE_BUMP) << "\n";
595 VLOG_INFO << "Use Voronoi " << string_from_bool(features & KERNEL_FEATURE_NODE_VORONOI_EXTRA)
596 << "\n";
597 VLOG_INFO << "Use Shader Raytrace " << string_from_bool(features & KERNEL_FEATURE_NODE_RAYTRACE)
598 << "\n";
599 VLOG_INFO << "Use MNEE " << string_from_bool(features & KERNEL_FEATURE_MNEE) << "\n";
600 VLOG_INFO << "Use Transparent " << string_from_bool(features & KERNEL_FEATURE_TRANSPARENT)
601 << "\n";
602 VLOG_INFO << "Use Denoising " << string_from_bool(features & KERNEL_FEATURE_DENOISING) << "\n";
603 VLOG_INFO << "Use Path Tracing " << string_from_bool(features & KERNEL_FEATURE_PATH_TRACING)
604 << "\n";
605 VLOG_INFO << "Use Hair " << string_from_bool(features & KERNEL_FEATURE_HAIR) << "\n";
606 VLOG_INFO << "Use Pointclouds " << string_from_bool(features & KERNEL_FEATURE_POINTCLOUD)
607 << "\n";
608 VLOG_INFO << "Use Object Motion " << string_from_bool(features & KERNEL_FEATURE_OBJECT_MOTION)
609 << "\n";
610 VLOG_INFO << "Use Baking " << string_from_bool(features & KERNEL_FEATURE_BAKING) << "\n";
611 VLOG_INFO << "Use Subsurface " << string_from_bool(features & KERNEL_FEATURE_SUBSURFACE) << "\n";
612 VLOG_INFO << "Use Volume " << string_from_bool(features & KERNEL_FEATURE_VOLUME) << "\n";
613 VLOG_INFO << "Use Patch Evaluation "
615 VLOG_INFO << "Use Shadow Catcher " << string_from_bool(features & KERNEL_FEATURE_SHADOW_CATCHER)
616 << "\n";
617}
618
620{
622
623 const uint kernel_features = dscene.data.kernel_features;
624
625 if (!kernels_loaded || loaded_kernel_features != kernel_features) {
626 progress.set_status("Loading render kernels (may take a few minutes the first time)");
627
629
630 log_kernel_features(kernel_features);
631 if (!device->load_kernels(kernel_features)) {
632 string message = device->error_message();
633 if (message.empty()) {
634 message = "Failed loading render kernel, see console for errors";
635 }
636
637 progress.set_error(message);
638 progress.set_status(message);
639 progress.set_update();
640 return false;
641 }
642
643 kernels_loaded = true;
644 loaded_kernel_features = kernel_features;
645 return true;
646 }
647 return false;
648}
649
651{
652 if (shader_manager->use_osl()) {
653 /* OSL always needs the maximum as we can't predict the
654 * number of closures a shader might generate. */
655 return MAX_CLOSURE;
656 }
657
658 int max_closures = 0;
659 for (int i = 0; i < shaders.size(); i++) {
660 Shader *shader = shaders[i];
661 if (shader->reference_count()) {
662 int num_closures = shader->graph->get_num_closures();
663 max_closures = max(max_closures, num_closures);
664 }
665 }
667
669 /* This is usually harmless as more complex shader tend to get many
670 * closures discarded due to mixing or low weights. We need to limit
671 * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
672 * avoids excessive memory usage for split kernels. */
673 VLOG_WARNING << "Maximum number of closures exceeded: " << max_closure_global << " > "
674 << MAX_CLOSURE;
675
677 }
678
679 return max_closure_global;
680}
681
683{
684 int volume_stack_size = 0;
685
686 /* Space for background volume and terminator.
687 * Don't do optional here because camera ray initialization expects that there is space for
688 * at least those elements (avoiding extra condition to check if there is actual volume or not).
689 */
690 volume_stack_size += 2;
691
692 /* Quick non-expensive check. Can over-estimate maximum possible nested level, but does not
693 * require expensive calculation during pre-processing. */
694 bool has_volume_object = false;
695 for (const Object *object : objects) {
696 if (!object->get_geometry()->has_volume) {
697 continue;
698 }
699
700 if (object->intersects_volume) {
701 /* Object intersects another volume, assume it's possible to go deeper in the stack. */
702 /* TODO(sergey): This might count nesting twice (A intersects B and B intersects A), but
703 * can't think of a computationally cheap algorithm. Dividing my 2 doesn't work because of
704 * Venn diagram example with 3 circles. */
705 ++volume_stack_size;
706 }
707 else if (!has_volume_object) {
708 /* Allocate space for at least one volume object. */
709 ++volume_stack_size;
710 }
711
712 has_volume_object = true;
713
714 if (volume_stack_size == MAX_VOLUME_STACK_SIZE) {
715 break;
716 }
717 }
718
719 volume_stack_size = min(volume_stack_size, MAX_VOLUME_STACK_SIZE);
720
721 VLOG_WORK << "Detected required volume stack size " << volume_stack_size;
722
723 return volume_stack_size;
724}
725
727{
729 has_shadow_catcher_ = false;
730 for (Object *object : objects) {
731 if (object->get_is_shadow_catcher()) {
732 has_shadow_catcher_ = true;
733 break;
734 }
735 }
736
738 }
739
740 return has_shadow_catcher_;
741}
742
747
749{
750 Light *node = new Light();
751 node->set_owner(this);
752 lights.push_back(node);
754 return node;
755}
756
758{
759 Mesh *node = new Mesh();
760 node->set_owner(this);
761 geometry.push_back(node);
763 return node;
764}
765
767{
768 Hair *node = new Hair();
769 node->set_owner(this);
770 geometry.push_back(node);
772 return node;
773}
774
776{
777 Volume *node = new Volume();
778 node->set_owner(this);
779 geometry.push_back(node);
781 return node;
782}
783
785{
786 PointCloud *node = new PointCloud();
787 node->set_owner(this);
788 geometry.push_back(node);
790 return node;
791}
792
794{
795 Object *node = new Object();
796 node->set_owner(this);
797 objects.push_back(node);
799 return node;
800}
801
803{
804 ParticleSystem *node = new ParticleSystem();
805 node->set_owner(this);
806 particle_systems.push_back(node);
808 return node;
809}
810
812{
813 Shader *node = new Shader();
814 node->set_owner(this);
815 shaders.push_back(node);
817 return node;
818}
819
820template<> AlembicProcedural *Scene::create_node<AlembicProcedural>()
821{
822#ifdef WITH_ALEMBIC
823 AlembicProcedural *node = new AlembicProcedural();
824 node->set_owner(this);
825 procedurals.push_back(node);
827 return node;
828#else
829 return nullptr;
830#endif
831}
832
834{
835 Pass *node = new Pass();
836 node->set_owner(this);
837 passes.push_back(node);
838 film->tag_modified();
839 return node;
840}
841
842template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
843{
844 for (size_t i = 0; i < nodes.size(); ++i) {
845 if (nodes[i] == node) {
846 std::swap(nodes[i], nodes[nodes.size() - 1]);
847 break;
848 }
849 }
850
851 nodes.resize(nodes.size() - 1);
852
853 delete node;
854}
855
861
862template<> void Scene::delete_node_impl(Mesh *node)
863{
864 delete_node_from_array(geometry, static_cast<Geometry *>(node));
866}
867
868template<> void Scene::delete_node_impl(Hair *node)
869{
870 delete_node_from_array(geometry, static_cast<Geometry *>(node));
872}
873
874template<> void Scene::delete_node_impl(Volume *node)
875{
876 delete_node_from_array(geometry, static_cast<Geometry *>(node));
878}
879
881{
882 delete_node_from_array(geometry, static_cast<Geometry *>(node));
884}
885
886template<> void Scene::delete_node_impl(Geometry *node)
887{
888 uint flag;
889 if (node->is_hair()) {
891 }
892 else {
894 }
895
896 delete_node_from_array(geometry, node);
898}
899
900template<> void Scene::delete_node_impl(Object *node)
901{
902 delete_node_from_array(objects, node);
904}
905
911
912template<> void Scene::delete_node_impl(Shader *shader)
913{
914 /* don't delete unused shaders, not supported */
915 shader->clear_reference_count();
916}
917
923
924template<> void Scene::delete_node_impl(AlembicProcedural *node)
925{
926#ifdef WITH_ALEMBIC
927 delete_node_impl(static_cast<Procedural *>(node));
928#else
929 (void)node;
930#endif
931}
932
933template<> void Scene::delete_node_impl(Pass *node)
934{
935 delete_node_from_array(passes, node);
936 film->tag_modified();
937}
938
939template<typename T>
940static void remove_nodes_in_set(const set<T *> &nodes_set,
941 vector<T *> &nodes_array,
942 const NodeOwner *owner)
943{
944 size_t new_size = nodes_array.size();
945
946 for (size_t i = 0; i < new_size; ++i) {
947 T *node = nodes_array[i];
948
949 if (nodes_set.find(node) != nodes_set.end()) {
950 std::swap(nodes_array[i], nodes_array[new_size - 1]);
951
952 assert(node->get_owner() == owner);
953 delete node;
954
955 i -= 1;
956 new_size -= 1;
957 }
958 }
959
960 nodes_array.resize(new_size);
961 (void)owner;
962}
963
964template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner)
965{
966 remove_nodes_in_set(nodes, lights, owner);
968}
969
970template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner)
971{
972 remove_nodes_in_set(nodes, geometry, owner);
974}
975
976template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner)
977{
978 remove_nodes_in_set(nodes, objects, owner);
980}
981
982template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner)
983{
986}
987
988template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner * /*owner*/)
989{
990 /* don't delete unused shaders, not supported */
991 for (Shader *shader : nodes) {
992 shader->clear_reference_count();
993 }
994}
995
996template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)
997{
998 remove_nodes_in_set(nodes, procedurals, owner);
1000}
1001
1002template<> void Scene::delete_nodes(const set<Pass *> &nodes, const NodeOwner *owner)
1003{
1004 remove_nodes_in_set(nodes, passes, owner);
1005 film->tag_modified();
1006}
1007
unsigned int uint
struct Light Light
struct Mesh Mesh
struct Object Object
struct ParticleSystem ParticleSystem
struct PointCloud PointCloud
struct Volume Volume
ATTR_WARN_UNUSED_RESULT const BMLoop * l
bool need_update() const
Definition bake.cpp:105
void device_free(Device *device, DeviceScene *dscene)
Definition bake.cpp:98
bool get_baking() const
Definition bake.cpp:25
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
Definition bake.cpp:59
KernelData data
Definition devicescene.h:95
virtual void optimize_for_scene(Scene *)
virtual const string & error_message()
virtual void const_copy_to(const char *name, void *host, size_t size)=0
virtual bool load_kernels(uint)
DeviceInfo info
bool have_error()
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void device_free(Device *device, DeviceScene *dscene, bool force_free)
void tag_update(Scene *scene, uint32_t flag)
void collect_statistics(const Scene *scene, RenderStats *stats)
void device_update_preprocess(Device *device, Scene *scene, Progress &progress)
bool need_update() const
bool is_pointcloud() const
bool is_hair() const
bool is_mesh() const
Definition hair.h:14
void device_update(Device *device, Scene *scene, Progress &progress)
bool need_update() const
void device_free(Device *device)
void device_free_builtin(Device *device)
void collect_statistics(RenderStats *stats)
void tag_update(Scene *scene, uint32_t flag)
void device_update(Device *device, DeviceScene *dscene, Scene *scene)
void device_free(Device *device, DeviceScene *dscene, bool force_free=false)
GuidingParams get_guiding_params(const Device *device) const
uint get_kernel_features() const
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void device_free(Device *device, DeviceScene *dscene, const bool free_background=true)
bool need_update() const
void tag_update(Scene *scene, uint32_t flag)
void device_free(Device *device, DeviceScene *dscene)
Definition tables.cpp:48
void device_update(Device *device, DeviceScene *dscene, Scene *scene)
Definition tables.cpp:27
bool need_update() const
Definition tables.cpp:53
void add_entry(const NamedTimeEntry &entry)
Definition scene/stats.h:69
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void tag_update(Scene *scene, uint32_t flag)
void device_free(Device *device, DeviceScene *dscene, bool force_free)
bool need_update() const
void device_update_prim_offsets(Device *device, DeviceScene *dscene, Scene *scene)
void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress, bool bounds_valid=true)
void device_free(Device *device, DeviceScene *dscene)
void tag_update(Scene *scene)
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
Definition pass.h:49
static bool contains(const vector< Pass * > &passes, PassType type)
Definition pass.cpp:368
bool need_update() const
void update(Scene *scene, Progress &progress)
bool get_cancel() const
Definition progress.h:93
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:263
void set_update()
Definition progress.h:321
void set_error(const string &error_message_)
Definition progress.h:113
bool background
Definition scene.h:75
CurveShapeType hair_shape
Definition scene.h:72
ShadingSystem shadingsystem
Definition scene.h:57
string full_report()
Definition stats.cpp:310
UpdateTimeStats scene
static ShaderManager * create(int shadingsystem, Device *device)
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene)=0
bool need_update() const
void tag_update(Scene *scene, uint32_t flag)
uint get_kernel_features(Scene *scene)
static void add_default(Scene *scene)
virtual bool use_osl()
virtual void reset(Scene *scene)=0
NODE_DECLARE ShaderGraph * graph
NamedTimeStats times
#define printf
OperationNode * node
#define CCL_NAMESPACE_END
#define NULL
size_t util_guarded_get_mem_used()
size_t util_guarded_get_mem_peak()
#define MEM_GUARDED_CALL(progress, func,...)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define KERNEL_FEATURE_VOLUME
#define MAX_VOLUME_STACK_SIZE
#define KERNEL_FEATURE_SHADOW_CATCHER
#define KERNEL_FEATURE_OBJECT_MOTION
AttributeStandard
@ ATTR_STD_UV
@ ATTR_STD_MOTION_VERTEX_NORMAL
@ ATTR_STD_VOLUME_VELOCITY_Y
@ ATTR_STD_NONE
@ ATTR_STD_VOLUME_VELOCITY_Z
@ ATTR_STD_NUM
@ ATTR_STD_VOLUME_VELOCITY
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_STD_VOLUME_VELOCITY_X
#define KERNEL_FEATURE_PATH_GUIDING
#define KERNEL_FEATURE_TRANSPARENT
@ CURVE_THICK
#define KERNEL_FEATURE_SUBSURFACE
#define KERNEL_FEATURE_NODE_BSDF
#define KERNEL_FEATURE_PATCH_EVALUATION
#define KERNEL_FEATURE_HAIR_THICK
#define KERNEL_FEATURE_NODE_VORONOI_EXTRA
#define KERNEL_FEATURE_NODE_VOLUME
#define KERNEL_FEATURE_PATH_TRACING
#define MAX_CLOSURE
@ PASS_UV
@ PASS_MOTION
#define KERNEL_FEATURE_SHADOW_LINKING
#define KERNEL_FEATURE_DENOISING
#define KERNEL_FEATURE_LIGHT_LINKING
#define KERNEL_FEATURE_HAIR
#define KERNEL_FEATURE_NODE_RAYTRACE
#define KERNEL_FEATURE_BAKING
#define KERNEL_FEATURE_MNEE
#define KERNEL_FEATURE_POINTCLOUD
#define KERNEL_FEATURE_NODE_EMISSION
#define KERNEL_FEATURE_NODE_BUMP
#define VLOG_INFO
Definition log.h:72
#define VLOG_WARNING
Definition log.h:70
#define VLOG_WORK
Definition log.h:75
@ SHADINGSYSTEM_SVM
void delete_node_from_array(vector< T > &nodes, T node)
Definition scene.cpp:842
static void log_kernel_features(const uint features)
Definition scene.cpp:587
static void remove_nodes_in_set(const set< T * > &nodes_set, vector< T * > &nodes_array, const NodeOwner *owner)
Definition scene.cpp:940
#define min(a, b)
Definition sort.c:32
string string_from_bool(bool var)
Definition string.cpp:170
string string_human_readable_size(size_t size)
Definition string.cpp:234
string string_human_readable_number(size_t num)
Definition string.cpp:255
@ SUBDIVISION_NONE
Definition scene/mesh.h:121
void tag_modified()
bool is_modified() const
bool kernels_loaded
Definition scene.h:251
BakeManager * bake_manager
Definition scene.h:146
Film * film
Definition scene.h:126
BVH * bvh
Definition scene.h:122
bool need_global_attribute(AttributeStandard std)
Definition scene.cpp:385
ParticleSystemManager * particle_system_manager
Definition scene.h:145
MotionType need_motion() const
Definition scene.cpp:362
void need_global_attributes(AttributeRequestSet &attributes)
Definition scene.cpp:405
Scene(const SceneParams &params, Device *device)
Definition scene.cpp:38
bool update(Progress &progress)
Definition scene.cpp:574
Device * device
Definition scene.h:157
vector< Procedural * > procedurals
Definition scene.h:137
int get_max_closure_count()
Definition scene.cpp:650
~Scene()
Definition scene.cpp:79
void device_free()
Definition scene.cpp:454
bool has_shadow_catcher_
Definition scene.h:256
Camera * dicing_camera
Definition scene.h:124
LookupTables * lookup_tables
Definition scene.h:125
SceneParams params
Definition scene.h:161
vector< Light * > lights
Definition scene.h:134
void tag_shadow_catcher_modified()
Definition scene.cpp:743
void free_memory(bool final)
Definition scene.cpp:84
vector< ParticleSystem * > particle_systems
Definition scene.h:135
ImageManager * image_manager
Definition scene.h:140
void enable_update_stats()
Definition scene.cpp:465
uint loaded_kernel_features
Definition scene.h:252
vector< Object * > objects
Definition scene.h:131
Light * create_node()
Definition scene.cpp:748
ObjectManager * object_manager
Definition scene.h:144
bool shadow_catcher_modified_
Definition scene.h:257
Background * background
Definition scene.h:127
MotionType
Definition scene.h:177
@ MOTION_PASS
Definition scene.h:177
@ MOTION_NONE
Definition scene.h:177
@ MOTION_BLUR
Definition scene.h:177
void update_kernel_features()
Definition scene.cpp:472
void delete_nodes(const set< T * > &nodes)
Definition scene.h:234
bool has_shadow_catcher()
Definition scene.cpp:726
ProceduralManager * procedural_manager
Definition scene.h:147
ShaderManager * shader_manager
Definition scene.h:142
void delete_node_impl(T *node)
Definition scene.h:268
bool load_kernels(Progress &progress)
Definition scene.cpp:619
int max_closure_global
Definition scene.h:260
Integrator * integrator
Definition scene.h:128
LightManager * light_manager
Definition scene.h:141
thread_mutex mutex
Definition scene.h:164
bool need_data_update()
Definition scene.cpp:419
int get_volume_stack_size() const
Definition scene.cpp:682
bool need_reset(const bool check_camera=true)
Definition scene.cpp:429
struct Object * camera
bool need_update()
Definition scene.cpp:414
void reset()
Definition scene.cpp:434
void collect_statistics(RenderStats *stats)
Definition scene.cpp:459
SceneUpdateStats * update_stats
Definition scene.h:167
GeometryManager * geometry_manager
Definition scene.h:143
DeviceScene dscene
Definition scene.h:158
float motion_shutter_time()
Definition scene.cpp:375
void device_update(Device *device, Progress &progress)
Definition scene.cpp:176
std::unique_lock< std::mutex > thread_scoped_lock
Definition thread.h:30
float max
wmTimer * timer