Blender V4.3
scene/geometry.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 "bvh/bvh.h"
6#include "bvh/bvh2.h"
7
8#include "device/device.h"
9
10#include "scene/attribute.h"
11#include "scene/camera.h"
12#include "scene/geometry.h"
13#include "scene/hair.h"
14#include "scene/light.h"
15#include "scene/mesh.h"
16#include "scene/object.h"
17#include "scene/osl.h"
18#include "scene/pointcloud.h"
19#include "scene/scene.h"
20#include "scene/shader.h"
21#include "scene/shader_nodes.h"
22#include "scene/stats.h"
23#include "scene/volume.h"
24
25#include "subd/patch_table.h"
26#include "subd/split.h"
27
28#ifdef WITH_OSL
29# include "kernel/osl/globals.h"
30#endif
31
32#include "util/foreach.h"
33#include "util/log.h"
34#include "util/progress.h"
35#include "util/task.h"
36
38
39/* Geometry */
40
42{
43 NodeType *type = NodeType::add("geometry_base", NULL);
44
45 SOCKET_UINT(motion_steps, "Motion Steps", 3);
46 SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
47 SOCKET_NODE_ARRAY(used_shaders, "Shaders", Shader::get_node_type());
48
49 return type;
50}
51
52Geometry::Geometry(const NodeType *node_type, const Type type)
53 : Node(node_type), geometry_type(type), attributes(this, ATTR_PRIM_GEOMETRY)
54{
55 need_update_rebuild = false;
57
58 transform_applied = false;
62
63 has_volume = false;
64 has_surface_bssrdf = false;
65
66 bvh = NULL;
68 prim_offset = 0;
69}
70
76
77void Geometry::clear(bool preserve_shaders)
78{
79 if (!preserve_shaders) {
80 used_shaders.clear();
81 }
82
83 transform_applied = false;
87}
88
89float Geometry::motion_time(int step) const
90{
91 return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
92}
93
94int Geometry::motion_step(float time) const
95{
96 if (motion_steps > 1) {
97 int attr_step = 0;
98
99 for (int step = 0; step < motion_steps; step++) {
100 float step_time = motion_time(step);
101 if (step_time == time) {
102 return attr_step;
103 }
104
105 /* Center step is stored in a separate attribute. */
106 if (step != motion_steps / 2) {
107 attr_step++;
108 }
109 }
110 }
111
112 return -1;
113}
114
116{
117 return is_instanced() || layout == BVH_LAYOUT_OPTIX || layout == BVH_LAYOUT_MULTI_OPTIX ||
118 layout == BVH_LAYOUT_METAL || layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE ||
120 layout == BVH_LAYOUT_HIPRT || layout == BVH_LAYOUT_MULTI_HIPRT ||
123}
124
126{
127 /* Currently we treat subsurface objects as instanced.
128 *
129 * While it might be not very optimal for ray traversal, it avoids having
130 * duplicated BVH in the memory, saving quite some space.
131 */
133}
134
136{
137 foreach (Node *node, used_shaders) {
138 Shader *shader = static_cast<Shader *>(node);
139 if (shader->has_displacement && shader->get_displacement_method() != DISPLACE_BUMP) {
140 return true;
141 }
142 }
143
144 return false;
145}
146
148{
149 return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION));
150}
151
152void Geometry::tag_update(Scene *scene, bool rebuild)
153{
154 if (rebuild) {
155 need_update_rebuild = true;
156 scene->light_manager->tag_update(scene, LightManager::MESH_NEED_REBUILD);
157 }
158 else {
159 foreach (Node *node, used_shaders) {
160 Shader *shader = static_cast<Shader *>(node);
161 if (shader->emission_sampling != EMISSION_SAMPLING_NONE) {
162 scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED);
163 break;
164 }
165 }
166 }
167
168 scene->geometry_manager->tag_update(scene, GeometryManager::GEOMETRY_MODIFIED);
169}
170
171void Geometry::tag_bvh_update(bool rebuild)
172{
173 tag_modified();
174
175 if (rebuild) {
176 need_update_rebuild = true;
177 }
178}
179
180/* Geometry Manager */
181
183{
184 update_flags = UPDATE_ALL;
185 need_flags_update = true;
186}
187
189
191{
192#ifdef WITH_OSL
193 OSLGlobals *og = (OSLGlobals *)device->get_cpu_osl_memory();
194 if (og == nullptr) {
195 /* Can happen when rendering with multiple GPUs, but no CPU (in which case the name maps filled
196 * below are not used anyway) */
197 return;
198 }
199
200 og->object_name_map.clear();
201 og->object_names.clear();
202
203 for (size_t i = 0; i < scene->objects.size(); i++) {
204 /* set object name to object index map */
205 Object *object = scene->objects[i];
206 og->object_name_map[object->name] = i;
207 og->object_names.push_back(object->name);
208 }
209#else
210 (void)device;
211 (void)scene;
212#endif
213}
214
215static void update_device_flags_attribute(uint32_t &device_update_flags,
216 const AttributeSet &attributes)
217{
218 foreach (const Attribute &attr, attributes.attributes) {
219 if (!attr.modified) {
220 continue;
221 }
222
223 AttrKernelDataType kernel_type = Attribute::kernel_type(attr);
224
225 switch (kernel_type) {
227 device_update_flags |= ATTR_FLOAT_MODIFIED;
228 break;
229 }
231 device_update_flags |= ATTR_FLOAT2_MODIFIED;
232 break;
233 }
235 device_update_flags |= ATTR_FLOAT3_MODIFIED;
236 break;
237 }
239 device_update_flags |= ATTR_FLOAT4_MODIFIED;
240 break;
241 }
243 device_update_flags |= ATTR_UCHAR4_MODIFIED;
244 break;
245 }
247 break;
248 }
249 }
250 }
251}
252
253static void update_attribute_realloc_flags(uint32_t &device_update_flags,
254 const AttributeSet &attributes)
255{
256 if (attributes.modified(AttrKernelDataType::FLOAT)) {
257 device_update_flags |= ATTR_FLOAT_NEEDS_REALLOC;
258 }
259 if (attributes.modified(AttrKernelDataType::FLOAT2)) {
260 device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC;
261 }
262 if (attributes.modified(AttrKernelDataType::FLOAT3)) {
263 device_update_flags |= ATTR_FLOAT3_NEEDS_REALLOC;
264 }
265 if (attributes.modified(AttrKernelDataType::FLOAT4)) {
266 device_update_flags |= ATTR_FLOAT4_NEEDS_REALLOC;
267 }
268 if (attributes.modified(AttrKernelDataType::UCHAR4)) {
269 device_update_flags |= ATTR_UCHAR4_NEEDS_REALLOC;
270 }
271}
272
274{
275 size_t vert_size = 0;
276 size_t tri_size = 0;
277
278 size_t curve_size = 0;
279 size_t curve_key_size = 0;
280 size_t curve_segment_size = 0;
281
282 size_t point_size = 0;
283
284 size_t patch_size = 0;
285 size_t face_size = 0;
286 size_t corner_size = 0;
287
288 foreach (Geometry *geom, scene->geometry) {
289 bool prim_offset_changed = false;
290
292 Mesh *mesh = static_cast<Mesh *>(geom);
293
294 prim_offset_changed = (mesh->prim_offset != tri_size);
295
296 mesh->vert_offset = vert_size;
297 mesh->prim_offset = tri_size;
298
299 mesh->patch_offset = patch_size;
300 mesh->face_offset = face_size;
301 mesh->corner_offset = corner_size;
302
303 vert_size += mesh->verts.size();
304 tri_size += mesh->num_triangles();
305
306 if (mesh->get_num_subd_faces()) {
307 Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1);
308 patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
309
310 /* patch tables are stored in same array so include them in patch_size */
311 if (mesh->patch_table) {
312 mesh->patch_table_offset = patch_size;
313 patch_size += mesh->patch_table->total_size();
314 }
315 }
316
317 face_size += mesh->get_num_subd_faces();
318 corner_size += mesh->subd_face_corners.size();
319 }
320 else if (geom->is_hair()) {
321 Hair *hair = static_cast<Hair *>(geom);
322
323 prim_offset_changed = (hair->curve_segment_offset != curve_segment_size);
324 hair->curve_key_offset = curve_key_size;
325 hair->curve_segment_offset = curve_segment_size;
326 hair->prim_offset = curve_size;
327
328 curve_size += hair->num_curves();
329 curve_key_size += hair->get_curve_keys().size();
330 curve_segment_size += hair->num_segments();
331 }
332 else if (geom->is_pointcloud()) {
333 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
334
335 prim_offset_changed = (pointcloud->prim_offset != point_size);
336
337 pointcloud->prim_offset = point_size;
338 point_size += pointcloud->num_points();
339 }
340
341 if (prim_offset_changed) {
342 /* Need to rebuild BVH in OptiX, since refit only allows modified mesh data there */
343 const bool has_optix_bvh = bvh_layout == BVH_LAYOUT_OPTIX ||
344 bvh_layout == BVH_LAYOUT_MULTI_OPTIX ||
345 bvh_layout == BVH_LAYOUT_MULTI_OPTIX_EMBREE;
346 geom->need_update_rebuild |= has_optix_bvh;
347 geom->need_update_bvh_for_offset = true;
348 }
349 }
350}
351
353{
354 if (!need_update() && !need_flags_update) {
355 return;
356 }
357
358 uint32_t device_update_flags = 0;
359
360 scoped_callback_timer timer([scene](double time) {
361 if (scene->update_stats) {
362 scene->update_stats->geometry.times.add_entry({"device_update_preprocess", time});
363 }
364 });
365
366 progress.set_status("Updating Meshes Flags");
367
368 /* Update flags. */
369 bool volume_images_updated = false;
370
371 foreach (Geometry *geom, scene->geometry) {
372 geom->has_volume = false;
373
374 update_attribute_realloc_flags(device_update_flags, geom->attributes);
375
376 if (geom->is_mesh()) {
377 Mesh *mesh = static_cast<Mesh *>(geom);
378 update_attribute_realloc_flags(device_update_flags, mesh->subd_attributes);
379 }
380
381 foreach (Node *node, geom->get_used_shaders()) {
382 Shader *shader = static_cast<Shader *>(node);
383 if (shader->has_volume) {
384 geom->has_volume = true;
385 }
386
387 if (shader->has_surface_bssrdf) {
388 geom->has_surface_bssrdf = true;
389 }
390
391 if (shader->need_update_uvs) {
392 device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC;
393
394 /* Attributes might need to be tessellated if added. */
395 if (geom->is_mesh()) {
396 Mesh *mesh = static_cast<Mesh *>(geom);
397 if (mesh->need_tesselation()) {
398 mesh->tag_modified();
399 }
400 }
401 }
402
403 if (shader->need_update_attribute) {
404 device_update_flags |= ATTRS_NEED_REALLOC;
405
406 /* Attributes might need to be tessellated if added. */
407 if (geom->is_mesh()) {
408 Mesh *mesh = static_cast<Mesh *>(geom);
409 if (mesh->need_tesselation()) {
410 mesh->tag_modified();
411 }
412 }
413 }
414
415 if (shader->need_update_displacement) {
416 /* tag displacement related sockets as modified */
417 if (geom->is_mesh()) {
418 Mesh *mesh = static_cast<Mesh *>(geom);
419 mesh->tag_verts_modified();
420 mesh->tag_subd_dicing_rate_modified();
421 mesh->tag_subd_max_level_modified();
422 mesh->tag_subd_objecttoworld_modified();
423
424 device_update_flags |= ATTRS_NEED_REALLOC;
425 }
426 }
427 }
428
429 /* only check for modified attributes if we do not need to reallocate them already */
430 if ((device_update_flags & ATTRS_NEED_REALLOC) == 0) {
431 update_device_flags_attribute(device_update_flags, geom->attributes);
432 /* don't check for subd_attributes, as if they were modified, we would need to reallocate
433 * anyway */
434 }
435
436 /* Re-create volume mesh if we will rebuild or refit the BVH. Note we
437 * should only do it in that case, otherwise the BVH and mesh can go
438 * out of sync. */
439 if (geom->is_modified() && geom->geometry_type == Geometry::VOLUME) {
440 /* Create volume meshes if there is voxel data. */
441 if (!volume_images_updated) {
442 progress.set_status("Updating Meshes Volume Bounds");
443 device_update_volume_images(device, scene, progress);
444 volume_images_updated = true;
445 }
446
447 Volume *volume = static_cast<Volume *>(geom);
448 create_volume_mesh(scene, volume, progress);
449
450 /* always reallocate when we have a volume, as we need to rebuild the BVH */
451 device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
452 }
453
454 if (geom->is_hair()) {
455 /* Set curve shape, still a global scene setting for now. */
456 Hair *hair = static_cast<Hair *>(geom);
457 hair->curve_shape = scene->params.hair_shape;
458
459 if (hair->need_update_rebuild) {
460 device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC;
461 }
462 else if (hair->is_modified()) {
463 device_update_flags |= DEVICE_CURVE_DATA_MODIFIED;
464 }
465 }
466
467 if (geom->is_mesh()) {
468 Mesh *mesh = static_cast<Mesh *>(geom);
469
470 if (mesh->need_update_rebuild) {
471 device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
472 }
473 else if (mesh->is_modified()) {
474 device_update_flags |= DEVICE_MESH_DATA_MODIFIED;
475 }
476 }
477
478 if (geom->is_pointcloud()) {
479 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
480
481 if (pointcloud->need_update_rebuild) {
482 device_update_flags |= DEVICE_POINT_DATA_NEEDS_REALLOC;
483 }
484 else if (pointcloud->is_modified()) {
485 device_update_flags |= DEVICE_POINT_DATA_MODIFIED;
486 }
487 }
488 }
489
490 if (update_flags & (MESH_ADDED | MESH_REMOVED)) {
491 device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
492 }
493
494 if (update_flags & (HAIR_ADDED | HAIR_REMOVED)) {
495 device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC;
496 }
497
498 if (update_flags & (POINT_ADDED | POINT_REMOVED)) {
499 device_update_flags |= DEVICE_POINT_DATA_NEEDS_REALLOC;
500 }
501
502 /* tag the device arrays for reallocation or modification */
503 DeviceScene *dscene = &scene->dscene;
504
507 {
508 delete scene->bvh;
509 scene->bvh = nullptr;
510
511 dscene->bvh_nodes.tag_realloc();
512 dscene->bvh_leaf_nodes.tag_realloc();
513 dscene->object_node.tag_realloc();
514 dscene->prim_type.tag_realloc();
516 dscene->prim_index.tag_realloc();
517 dscene->prim_object.tag_realloc();
518 dscene->prim_time.tag_realloc();
519
520 if (device_update_flags & DEVICE_MESH_DATA_NEEDS_REALLOC) {
521 dscene->tri_verts.tag_realloc();
522 dscene->tri_vnormal.tag_realloc();
523 dscene->tri_vindex.tag_realloc();
524 dscene->tri_patch.tag_realloc();
525 dscene->tri_patch_uv.tag_realloc();
526 dscene->tri_shader.tag_realloc();
527 dscene->patches.tag_realloc();
528 }
529
530 if (device_update_flags & DEVICE_CURVE_DATA_NEEDS_REALLOC) {
531 dscene->curves.tag_realloc();
532 dscene->curve_keys.tag_realloc();
533 dscene->curve_segments.tag_realloc();
534 }
535
536 if (device_update_flags & DEVICE_POINT_DATA_NEEDS_REALLOC) {
537 dscene->points.tag_realloc();
538 dscene->points_shader.tag_realloc();
539 }
540 }
541
542 if ((update_flags & VISIBILITY_MODIFIED) != 0) {
544 }
545
546 if (device_update_flags & ATTR_FLOAT_NEEDS_REALLOC) {
547 dscene->attributes_map.tag_realloc();
549 }
550 else if (device_update_flags & ATTR_FLOAT_MODIFIED) {
552 }
553
554 if (device_update_flags & ATTR_FLOAT2_NEEDS_REALLOC) {
555 dscene->attributes_map.tag_realloc();
557 }
558 else if (device_update_flags & ATTR_FLOAT2_MODIFIED) {
560 }
561
562 if (device_update_flags & ATTR_FLOAT3_NEEDS_REALLOC) {
563 dscene->attributes_map.tag_realloc();
565 }
566 else if (device_update_flags & ATTR_FLOAT3_MODIFIED) {
568 }
569
570 if (device_update_flags & ATTR_FLOAT4_NEEDS_REALLOC) {
571 dscene->attributes_map.tag_realloc();
573 }
574 else if (device_update_flags & ATTR_FLOAT4_MODIFIED) {
576 }
577
578 if (device_update_flags & ATTR_UCHAR4_NEEDS_REALLOC) {
579 dscene->attributes_map.tag_realloc();
581 }
582 else if (device_update_flags & ATTR_UCHAR4_MODIFIED) {
584 }
585
586 if (device_update_flags & DEVICE_MESH_DATA_MODIFIED) {
587 /* if anything else than vertices or shaders are modified, we would need to reallocate, so
588 * these are the only arrays that can be updated */
589 dscene->tri_verts.tag_modified();
590 dscene->tri_vnormal.tag_modified();
591 dscene->tri_shader.tag_modified();
592 }
593
594 if (device_update_flags & DEVICE_CURVE_DATA_MODIFIED) {
595 dscene->curve_keys.tag_modified();
596 dscene->curves.tag_modified();
598 }
599
600 if (device_update_flags & DEVICE_POINT_DATA_MODIFIED) {
601 dscene->points.tag_modified();
602 dscene->points_shader.tag_modified();
603 }
604
605 need_flags_update = false;
606}
607
609 Scene *scene,
610 Progress &progress)
611{
612 progress.set_status("Updating Displacement Images");
613 TaskPool pool;
614 ImageManager *image_manager = scene->image_manager;
615 set<int> bump_images;
616#ifdef WITH_OSL
617 bool has_osl_node = false;
618#endif
619 foreach (Geometry *geom, scene->geometry) {
620 if (geom->is_modified()) {
621 /* Geometry-level check for hair shadow transparency.
622 * This matches the logic in the `Hair::update_shadow_transparency()`, avoiding access to
623 * possible non-loaded images. */
624 bool need_shadow_transparency = false;
625 if (geom->geometry_type == Geometry::HAIR) {
626 Hair *hair = static_cast<Hair *>(geom);
627 need_shadow_transparency = hair->need_shadow_transparency();
628 }
629
630 foreach (Node *node, geom->get_used_shaders()) {
631 Shader *shader = static_cast<Shader *>(node);
632 const bool is_true_displacement = (shader->has_displacement &&
633 shader->get_displacement_method() != DISPLACE_BUMP);
634 if (!is_true_displacement && !need_shadow_transparency) {
635 continue;
636 }
637 foreach (ShaderNode *node, shader->graph->nodes) {
638#ifdef WITH_OSL
639 if (node->special_type == SHADER_SPECIAL_TYPE_OSL) {
640 has_osl_node = true;
641 }
642#endif
643 if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
644 continue;
645 }
646
647 ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node);
648 for (int i = 0; i < image_node->handle.num_tiles(); i++) {
649 const int slot = image_node->handle.svm_slot(i);
650 if (slot != -1) {
651 bump_images.insert(slot);
652 }
653 }
654 }
655 }
656 }
657 }
658
659#ifdef WITH_OSL
660 /* If any OSL node is used for displacement, it may reference a texture. But it's
661 * unknown which ones, so have to load them all. */
662 if (has_osl_node) {
663 OSLShaderManager::osl_image_slots(device, image_manager, bump_images);
664 }
665#endif
666
667 foreach (int slot, bump_images) {
668 pool.push(function_bind(
669 &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
670 }
671 pool.wait_work();
672}
673
675{
676 progress.set_status("Updating Volume Images");
677 TaskPool pool;
678 ImageManager *image_manager = scene->image_manager;
679 set<int> volume_images;
680
681 foreach (Geometry *geom, scene->geometry) {
682 if (!geom->is_modified()) {
683 continue;
684 }
685
686 foreach (Attribute &attr, geom->attributes.attributes) {
687 if (attr.element != ATTR_ELEMENT_VOXEL) {
688 continue;
689 }
690
691 ImageHandle &handle = attr.data_voxel();
692 /* We can build directly from OpenVDB data structures, no need to
693 * load such images early. */
694 if (!handle.vdb_loader()) {
695 const int slot = handle.svm_slot();
696 if (slot != -1) {
697 volume_images.insert(slot);
698 }
699 }
700 }
701 }
702
703 foreach (int slot, volume_images) {
704 pool.push(function_bind(
705 &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
706 }
707 pool.wait_work();
708}
709
711 DeviceScene *dscene,
712 Scene *scene,
713 Progress &progress)
714{
715 if (!need_update()) {
716 return;
717 }
718
719 VLOG_INFO << "Total " << scene->geometry.size() << " meshes.";
720
721 bool true_displacement_used = false;
722 bool curve_shadow_transparency_used = false;
723 size_t total_tess_needed = 0;
724
725 {
726 scoped_callback_timer timer([scene](double time) {
727 if (scene->update_stats) {
728 scene->update_stats->geometry.times.add_entry({"device_update (normals)", time});
729 }
730 });
731
732 foreach (Geometry *geom, scene->geometry) {
733 if (geom->is_modified()) {
734 if ((geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) {
735 Mesh *mesh = static_cast<Mesh *>(geom);
736
737 /* Update normals. */
738 mesh->add_face_normals();
739 mesh->add_vertex_normals();
740
741 if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
742 mesh->add_undisplaced();
743 }
744
745 /* Test if we need tessellation. */
746 if (mesh->need_tesselation()) {
747 total_tess_needed++;
748 }
749
750 /* Test if we need displacement. */
751 if (mesh->has_true_displacement()) {
752 true_displacement_used = true;
753 }
754 }
755 else if (geom->geometry_type == Geometry::HAIR) {
756 Hair *hair = static_cast<Hair *>(geom);
757 if (hair->need_shadow_transparency()) {
758 curve_shadow_transparency_used = true;
759 }
760 }
761
762 if (progress.get_cancel()) {
763 return;
764 }
765 }
766 }
767 }
768
769 if (progress.get_cancel()) {
770 return;
771 }
772
773 /* Tessellate meshes that are using subdivision */
774 if (total_tess_needed) {
775 scoped_callback_timer timer([scene](double time) {
776 if (scene->update_stats) {
777 scene->update_stats->geometry.times.add_entry(
778 {"device_update (adaptive subdivision)", time});
779 }
780 });
781
782 Camera *dicing_camera = scene->dicing_camera;
783 dicing_camera->set_screen_size(dicing_camera->get_full_width(),
784 dicing_camera->get_full_height());
785 dicing_camera->update(scene);
786
787 size_t i = 0;
788 foreach (Geometry *geom, scene->geometry) {
789 if (!(geom->is_modified() && geom->is_mesh())) {
790 continue;
791 }
792
793 Mesh *mesh = static_cast<Mesh *>(geom);
794 if (mesh->need_tesselation()) {
795 string msg = "Tessellating ";
796 if (mesh->name == "") {
797 msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
798 }
799 else {
800 msg += string_printf(
801 "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
802 }
803
804 progress.set_status("Updating Mesh", msg);
805
806 mesh->subd_params->camera = dicing_camera;
807 DiagSplit dsplit(*mesh->subd_params);
808 mesh->tessellate(&dsplit);
809
810 i++;
811
812 if (progress.get_cancel()) {
813 return;
814 }
815 }
816 }
817
818 if (progress.get_cancel()) {
819 return;
820 }
821 }
822
823 /* Update images needed for true displacement. */
824 if (true_displacement_used || curve_shadow_transparency_used) {
825 scoped_callback_timer timer([scene](double time) {
826 if (scene->update_stats) {
827 scene->update_stats->geometry.times.add_entry(
828 {"device_update (displacement: load images)", time});
829 }
830 });
831 device_update_displacement_images(device, scene, progress);
832 scene->object_manager->device_update_flags(device, dscene, scene, progress, false);
833 }
834
835 /* Device update. */
836 device_free(device, dscene, false);
837
838 const BVHLayout bvh_layout = BVHParams::best_bvh_layout(
839 scene->params.bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
840 geom_calc_offset(scene, bvh_layout);
841 if (true_displacement_used || curve_shadow_transparency_used) {
842 scoped_callback_timer timer([scene](double time) {
843 if (scene->update_stats) {
844 scene->update_stats->geometry.times.add_entry(
845 {"device_update (displacement: copy meshes to device)", time});
846 }
847 });
848 device_update_mesh(device, dscene, scene, progress);
849 }
850 if (progress.get_cancel()) {
851 return;
852 }
853
854 {
855 scoped_callback_timer timer([scene](double time) {
856 if (scene->update_stats) {
857 scene->update_stats->geometry.times.add_entry({"device_update (attributes)", time});
858 }
859 });
860 device_update_attributes(device, dscene, scene, progress);
861 if (progress.get_cancel()) {
862 return;
863 }
864 }
865
866 /* Update displacement and hair shadow transparency. */
867 bool displacement_done = false;
868 bool curve_shadow_transparency_done = false;
869 size_t num_bvh = 0;
870
871 {
872 /* Copy constant data needed by shader evaluation. */
873 device->const_copy_to("data", &dscene->data, sizeof(dscene->data));
874
875 scoped_callback_timer timer([scene](double time) {
876 if (scene->update_stats) {
877 scene->update_stats->geometry.times.add_entry({"device_update (displacement)", time});
878 }
879 });
880
881 foreach (Geometry *geom, scene->geometry) {
882 if (geom->is_modified()) {
883 if (geom->is_mesh()) {
884 Mesh *mesh = static_cast<Mesh *>(geom);
885 if (displace(device, scene, mesh, progress)) {
886 displacement_done = true;
887 }
888 }
889 else if (geom->geometry_type == Geometry::HAIR) {
890 Hair *hair = static_cast<Hair *>(geom);
891 if (hair->update_shadow_transparency(device, scene, progress)) {
892 curve_shadow_transparency_done = true;
893 }
894 }
895 }
896
897 if (geom->is_modified() || geom->need_update_bvh_for_offset) {
898 if (geom->need_build_bvh(bvh_layout)) {
899 num_bvh++;
900 }
901 }
902
903 if (progress.get_cancel()) {
904 return;
905 }
906 }
907 }
908
909 if (progress.get_cancel()) {
910 return;
911 }
912
913 /* Device re-update after displacement. */
914 if (displacement_done || curve_shadow_transparency_done) {
915 scoped_callback_timer timer([scene](double time) {
916 if (scene->update_stats) {
917 scene->update_stats->geometry.times.add_entry(
918 {"device_update (displacement: attributes)", time});
919 }
920 });
921 device_free(device, dscene, false);
922
923 device_update_attributes(device, dscene, scene, progress);
924 if (progress.get_cancel()) {
925 return;
926 }
927 }
928
929 /* Update the BVH even when there is no geometry so the kernel's BVH data is still valid,
930 * especially when removing all of the objects during interactive renders.
931 * Also update the BVH if the transformations change, we cannot rely on tagging the Geometry
932 * as modified in this case, as we may accumulate displacement if the vertices do not also
933 * change. */
934 bool need_update_scene_bvh = (scene->bvh == nullptr ||
935 (update_flags & (TRANSFORM_MODIFIED | VISIBILITY_MODIFIED)) != 0);
936 {
937 scoped_callback_timer timer([scene](double time) {
938 if (scene->update_stats) {
939 scene->update_stats->geometry.times.add_entry({"device_update (build object BVHs)", time});
940 }
941 });
943
944 size_t i = 0;
945 foreach (Geometry *geom, scene->geometry) {
946 if (geom->is_modified() || geom->need_update_bvh_for_offset) {
947 need_update_scene_bvh = true;
949 &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh));
950 if (geom->need_build_bvh(bvh_layout)) {
951 i++;
952 }
953 }
954 }
955
956 TaskPool::Summary summary;
957 pool.wait_work(&summary);
958 VLOG_WORK << "Objects BVH build pool statistics:\n" << summary.full_report();
959 }
960
961 foreach (Shader *shader, scene->shaders) {
962 shader->need_update_uvs = false;
963 shader->need_update_attribute = false;
964 shader->need_update_displacement = false;
965 }
966
967 Scene::MotionType need_motion = scene->need_motion();
968 bool motion_blur = need_motion == Scene::MOTION_BLUR;
969
970 /* Update objects. */
971 {
972 scoped_callback_timer timer([scene](double time) {
973 if (scene->update_stats) {
974 scene->update_stats->geometry.times.add_entry({"device_update (compute bounds)", time});
975 }
976 });
977 foreach (Object *object, scene->objects) {
978 object->compute_bounds(motion_blur);
979 }
980 }
981
982 if (progress.get_cancel()) {
983 return;
984 }
985
986 if (need_update_scene_bvh) {
987 scoped_callback_timer timer([scene](double time) {
988 if (scene->update_stats) {
989 scene->update_stats->geometry.times.add_entry({"device_update (build scene BVH)", time});
990 }
991 });
992 device_update_bvh(device, dscene, scene, progress);
993 if (progress.get_cancel()) {
994 return;
995 }
996 }
997
998 /* Always set BVH layout again after displacement where it was set to none,
999 * to avoid ray-tracing at that stage. */
1000 dscene->data.bvh.bvh_layout = BVHParams::best_bvh_layout(
1001 scene->params.bvh_layout, device->get_bvh_layout_mask(dscene->data.kernel_features));
1002
1003 {
1004 scoped_callback_timer timer([scene](double time) {
1005 if (scene->update_stats) {
1006 scene->update_stats->geometry.times.add_entry(
1007 {"device_update (copy meshes to device)", time});
1008 }
1009 });
1010 device_update_mesh(device, dscene, scene, progress);
1011 if (progress.get_cancel()) {
1012 return;
1013 }
1014 }
1015
1016 /* unset flags */
1017
1018 foreach (Geometry *geom, scene->geometry) {
1019 geom->clear_modified();
1020 geom->attributes.clear_modified();
1021
1022 if (geom->is_mesh()) {
1023 Mesh *mesh = static_cast<Mesh *>(geom);
1025 }
1026 }
1027
1028 update_flags = UPDATE_NONE;
1029
1030 dscene->bvh_nodes.clear_modified();
1032 dscene->object_node.clear_modified();
1033 dscene->prim_type.clear_modified();
1035 dscene->prim_index.clear_modified();
1036 dscene->prim_object.clear_modified();
1037 dscene->prim_time.clear_modified();
1038 dscene->tri_verts.clear_modified();
1039 dscene->tri_shader.clear_modified();
1040 dscene->tri_vindex.clear_modified();
1041 dscene->tri_patch.clear_modified();
1042 dscene->tri_vnormal.clear_modified();
1043 dscene->tri_patch_uv.clear_modified();
1044 dscene->curves.clear_modified();
1045 dscene->curve_keys.clear_modified();
1047 dscene->points.clear_modified();
1048 dscene->points_shader.clear_modified();
1049 dscene->patches.clear_modified();
1056}
1057
1058void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool force_free)
1059{
1060 dscene->bvh_nodes.free_if_need_realloc(force_free);
1061 dscene->bvh_leaf_nodes.free_if_need_realloc(force_free);
1062 dscene->object_node.free_if_need_realloc(force_free);
1063 dscene->prim_type.free_if_need_realloc(force_free);
1064 dscene->prim_visibility.free_if_need_realloc(force_free);
1065 dscene->prim_index.free_if_need_realloc(force_free);
1066 dscene->prim_object.free_if_need_realloc(force_free);
1067 dscene->prim_time.free_if_need_realloc(force_free);
1068 dscene->tri_verts.free_if_need_realloc(force_free);
1069 dscene->tri_shader.free_if_need_realloc(force_free);
1070 dscene->tri_vnormal.free_if_need_realloc(force_free);
1071 dscene->tri_vindex.free_if_need_realloc(force_free);
1072 dscene->tri_patch.free_if_need_realloc(force_free);
1073 dscene->tri_patch_uv.free_if_need_realloc(force_free);
1074 dscene->curves.free_if_need_realloc(force_free);
1075 dscene->curve_keys.free_if_need_realloc(force_free);
1076 dscene->curve_segments.free_if_need_realloc(force_free);
1077 dscene->points.free_if_need_realloc(force_free);
1078 dscene->points_shader.free_if_need_realloc(force_free);
1079 dscene->patches.free_if_need_realloc(force_free);
1080 dscene->attributes_map.free_if_need_realloc(force_free);
1081 dscene->attributes_float.free_if_need_realloc(force_free);
1082 dscene->attributes_float2.free_if_need_realloc(force_free);
1083 dscene->attributes_float3.free_if_need_realloc(force_free);
1084 dscene->attributes_float4.free_if_need_realloc(force_free);
1085 dscene->attributes_uchar4.free_if_need_realloc(force_free);
1086
1087 /* Signal for shaders like displacement not to do ray tracing. */
1088 dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE;
1089
1090#ifdef WITH_OSL
1091 OSLGlobals *og = (OSLGlobals *)device->get_cpu_osl_memory();
1092
1093 if (og) {
1094 og->object_name_map.clear();
1095 og->object_names.clear();
1096 }
1097#else
1098 (void)device;
1099#endif
1100}
1101
1103{
1104 update_flags |= flag;
1105
1106 /* do not tag the object manager for an update if it is the one who tagged us */
1107 if ((flag & OBJECT_MANAGER) == 0) {
1108 scene->object_manager->tag_update(scene, ObjectManager::GEOMETRY_MANAGER);
1109 }
1110}
1111
1113{
1114 return update_flags != UPDATE_NONE;
1115}
1116
1118{
1119 foreach (Geometry *geometry, scene->geometry) {
1120 stats->mesh.geometry.add_entry(
1121 NamedSizeEntry(string(geometry->name.c_str()), geometry->get_total_size_in_bytes()));
1122 }
1123}
1124
unsigned int uint
list< Attribute > attributes
AttributeElement element
static AttrKernelDataType kernel_type(const Attribute &attr)
ImageHandle & data_voxel()
static BVHLayout best_bvh_layout(BVHLayout requested_layout, BVHLayoutMask supported_layouts)
Definition bvh.cpp:57
device_vector< uint > points_shader
Definition devicescene.h:44
device_vector< float2 > prim_time
Definition devicescene.h:26
device_vector< uint > patches
Definition devicescene.h:40
device_vector< float4 > points
Definition devicescene.h:43
device_vector< uint > prim_visibility
Definition devicescene.h:23
device_vector< float4 > attributes_float4
Definition devicescene.h:62
device_vector< KernelCurveSegment > curve_segments
Definition devicescene.h:38
device_vector< float2 > attributes_float2
Definition devicescene.h:60
device_vector< AttributeMap > attributes_map
Definition devicescene.h:58
device_vector< KernelCurve > curves
Definition devicescene.h:36
device_vector< packed_uint3 > tri_vindex
Definition devicescene.h:32
device_vector< int > object_node
Definition devicescene.h:21
device_vector< packed_float3 > attributes_float3
Definition devicescene.h:61
device_vector< int > prim_object
Definition devicescene.h:25
device_vector< float4 > curve_keys
Definition devicescene.h:37
device_vector< packed_float3 > tri_vnormal
Definition devicescene.h:31
device_vector< int4 > bvh_leaf_nodes
Definition devicescene.h:20
device_vector< uint > tri_shader
Definition devicescene.h:30
device_vector< packed_float3 > tri_verts
Definition devicescene.h:29
device_vector< float > attributes_float
Definition devicescene.h:59
device_vector< float2 > tri_patch_uv
Definition devicescene.h:34
device_vector< uint > tri_patch
Definition devicescene.h:33
KernelData data
Definition devicescene.h:95
device_vector< int > prim_type
Definition devicescene.h:22
device_vector< int4 > bvh_nodes
Definition devicescene.h:19
device_vector< int > prim_index
Definition devicescene.h:24
device_vector< uchar4 > attributes_uchar4
Definition devicescene.h:63
virtual void * get_cpu_osl_memory()
void device_update_displacement_images(Device *device, Scene *scene, Progress &progress)
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress)
void geom_calc_offset(Scene *scene, BVHLayout bvh_layout)
void update_osl_globals(Device *device, Scene *scene)
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)
void device_update_volume_images(Device *device, Scene *scene, Progress &progress)
bool need_update() const
Transform transform_normal
void compute_bvh(Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, size_t n, size_t total)
float motion_time(int step) const
Type geometry_type
BoundBox bounds
bool need_update_bvh_for_offset
bool transform_applied
bool has_true_displacement() const
bool need_build_bvh(BVHLayout layout) const
bool is_pointcloud() const
int motion_step(float time) const
bool is_hair() const
bool has_surface_bssrdf
bool is_instanced() const
size_t attr_map_offset
size_t prim_offset
bool has_motion_blur() const
void tag_update(Scene *scene, bool rebuild)
bool need_update_rebuild
AttributeSet attributes
bool is_mesh() const
virtual ~Geometry()
Geometry(const NodeType *node_type, const Type type)
bool transform_negative_scaled
void tag_bvh_update(bool rebuild)
virtual void clear(bool preserve_shaders=false)
Definition hair.h:14
bool need_shadow_transparency()
Definition hair.cpp:601
size_t curve_key_offset
Definition hair.h:90
CurveShapeType curve_shape
Definition hair.h:92
int num_tiles() const
int svm_slot(const int tile_index=0) const
void device_update_slot(Device *device, Scene *scene, size_t slot, Progress *progress)
NamedSizeStats geometry
void add_entry(const NamedSizeEntry &entry)
Definition stats.cpp:56
bool get_cancel() const
Definition progress.h:93
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:263
void tag_update(Scene *scene)
void free_if_need_realloc(bool force_free)
OperationNode * node
#define function_bind
#define CCL_NAMESPACE_END
#define NULL
@ ATTR_STD_POSITION_UNDISPLACED
@ ATTR_STD_MOTION_VERTEX_POSITION
@ EMISSION_SAMPLING_NONE
@ BVH_LAYOUT_OPTIX
@ BVH_LAYOUT_MULTI_HIPRT_EMBREE
@ BVH_LAYOUT_NONE
@ BVH_LAYOUT_MULTI_EMBREEGPU
@ BVH_LAYOUT_METAL
@ BVH_LAYOUT_MULTI_HIPRT
@ BVH_LAYOUT_HIPRT
@ BVH_LAYOUT_MULTI_OPTIX
@ BVH_LAYOUT_EMBREEGPU
@ BVH_LAYOUT_MULTI_METAL
@ BVH_LAYOUT_MULTI_METAL_EMBREE
@ BVH_LAYOUT_MULTI_EMBREEGPU_EMBREE
@ BVH_LAYOUT_MULTI_OPTIX_EMBREE
@ ATTR_ELEMENT_VOXEL
@ ATTR_PRIM_GEOMETRY
#define VLOG_INFO
Definition log.h:72
#define VLOG_WORK
Definition log.h:75
#define SOCKET_NODE_ARRAY(name, ui_name, node_type,...)
Definition node_type.h:277
#define SOCKET_UINT(name, ui_name, default_value,...)
Definition node_type.h:196
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition node_type.h:192
#define NODE_ABSTRACT_DEFINE(structname)
Definition node_type.h:164
CCL_NAMESPACE_BEGIN typedef KernelBVHLayout BVHLayout
Definition params.h:23
AttrKernelDataType
@ FLOAT4
@ NUM
@ FLOAT2
@ UCHAR4
@ FLOAT3
@ FLOAT
static void update_device_flags_attribute(uint32_t &device_update_flags, const AttributeSet &attributes)
static void update_attribute_realloc_flags(uint32_t &device_update_flags, const AttributeSet &attributes)
@ ATTR_FLOAT4_MODIFIED
@ ATTR_UCHAR4_MODIFIED
@ DEVICE_MESH_DATA_NEEDS_REALLOC
@ ATTR_FLOAT3_MODIFIED
@ DEVICE_POINT_DATA_MODIFIED
@ DEVICE_POINT_DATA_NEEDS_REALLOC
@ ATTR_FLOAT4_NEEDS_REALLOC
@ ATTR_UCHAR4_NEEDS_REALLOC
@ ATTR_FLOAT_MODIFIED
@ ATTR_FLOAT2_NEEDS_REALLOC
@ DEVICE_MESH_DATA_MODIFIED
@ DEVICE_CURVE_DATA_MODIFIED
@ ATTR_FLOAT2_MODIFIED
@ ATTR_FLOAT_NEEDS_REALLOC
@ DEVICE_CURVE_DATA_NEEDS_REALLOC
@ ATTR_FLOAT3_NEEDS_REALLOC
@ ATTRS_NEED_REALLOC
@ DISPLACE_BUMP
@ SHADER_SPECIAL_TYPE_IMAGE_SLOT
@ SHADER_SPECIAL_TYPE_OSL
unsigned int uint32_t
Definition stdint.h:80
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
void set_screen_size(int width_, int height_)
void update(Scene *scene)
int num_ptex_faces() const
Definition scene/mesh.h:98
AttributeSet subd_attributes
Definition scene/mesh.h:159
void add_face_normals()
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
void dereference_all_used_nodes()
void clear_modified()
void tag_modified()
bool is_modified() const
size_t num_points() const
MeshStats mesh
MotionType
Definition scene.h:177
@ MOTION_BLUR
Definition scene.h:177
string full_report() const
Definition task.cpp:235
void push(TaskRunFunction &&task)
Definition task.cpp:22
void wait_work(Summary *stats=NULL)
Definition task.cpp:28
ccl_device_inline Transform transform_identity()
Definition transform.h:296
wmTimer * timer
uint8_t flag
Definition wm_window.cc:138