diff options
Diffstat (limited to 'intern/cycles/render/geometry.cpp')
-rw-r--r-- | intern/cycles/render/geometry.cpp | 131 |
1 files changed, 94 insertions, 37 deletions
diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index bd2b8164cbb..1c4b360750f 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -46,6 +46,12 @@ CCL_NAMESPACE_BEGIN /* Geometry */ +PackFlags operator|=(PackFlags &pack_flags, uint32_t value) +{ + pack_flags = (PackFlags)((uint32_t)pack_flags | value); + return pack_flags; +} + NODE_ABSTRACT_DEFINE(Geometry) { NodeType *type = NodeType::add("geometry_base", NULL); @@ -79,6 +85,7 @@ Geometry::Geometry(const NodeType *node_type, const Type type) Geometry::~Geometry() { + dereference_all_used_nodes(); delete bvh; } @@ -823,10 +830,13 @@ void GeometryManager::device_update_attributes(Device *device, dscene->attributes_float3.alloc(attr_float3_size); dscene->attributes_uchar4.alloc(attr_uchar4_size); - const bool copy_all_data = dscene->attributes_float.need_realloc() || - dscene->attributes_float2.need_realloc() || - dscene->attributes_float3.need_realloc() || - dscene->attributes_uchar4.need_realloc(); + /* The order of those flags needs to match that of AttrKernelDataType. */ + const bool attributes_need_realloc[4] = { + dscene->attributes_float.need_realloc(), + dscene->attributes_float2.need_realloc(), + dscene->attributes_float3.need_realloc(), + dscene->attributes_uchar4.need_realloc(), + }; size_t attr_float_offset = 0; size_t attr_float2_offset = 0; @@ -845,7 +855,7 @@ void GeometryManager::device_update_attributes(Device *device, if (attr) { /* force a copy if we need to reallocate all the data */ - attr->modified |= copy_all_data; + attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)]; } update_attribute_element_offset(geom, @@ -868,7 +878,7 @@ void GeometryManager::device_update_attributes(Device *device, if (subd_attr) { /* force a copy if we need to reallocate all the data */ - subd_attr->modified |= copy_all_data; + subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)]; } update_attribute_element_offset(mesh, @@ -899,6 +909,10 @@ void GeometryManager::device_update_attributes(Device *device, foreach (AttributeRequest &req, attributes.requests) { Attribute *attr = values.find(req); + if (attr) { + attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)]; + } + update_attribute_element_offset(object->geometry, dscene->attributes_float, attr_float_offset, @@ -934,10 +948,10 @@ void GeometryManager::device_update_attributes(Device *device, /* copy to device */ progress.set_status("Updating Mesh", "Copying Attributes to device"); - dscene->attributes_float.copy_to_device(); - dscene->attributes_float2.copy_to_device(); - dscene->attributes_float3.copy_to_device(); - dscene->attributes_uchar4.copy_to_device(); + dscene->attributes_float.copy_to_device_if_modified(); + dscene->attributes_float2.copy_to_device_if_modified(); + dscene->attributes_float3.copy_to_device_if_modified(); + dscene->attributes_uchar4.copy_to_device_if_modified(); if (progress.get_cancel()) return; @@ -1235,7 +1249,16 @@ void GeometryManager::device_update_bvh(Device *device, const bool can_refit = scene->bvh != nullptr && (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX); - const bool pack_all = scene->bvh == nullptr; + + PackFlags pack_flags = PackFlags::PACK_NONE; + + if (scene->bvh == nullptr) { + pack_flags |= PackFlags::PACK_ALL; + } + + if (dscene->prim_visibility.is_modified()) { + pack_flags |= PackFlags::PACK_VISIBILITY; + } BVH *bvh = scene->bvh; if (!scene->bvh) { @@ -1273,10 +1296,14 @@ void GeometryManager::device_update_bvh(Device *device, pack.root_index = -1; - if (!pack_all) { + if (pack_flags != PackFlags::PACK_ALL) { /* if we do not need to recreate the BVH, then only the vertices are updated, so we can * safely retake the memory */ dscene->prim_tri_verts.give_data(pack.prim_tri_verts); + + if ((pack_flags & PackFlags::PACK_VISIBILITY) != 0) { + dscene->prim_visibility.give_data(pack.prim_visibility); + } } else { /* It is not strictly necessary to skip those resizes we if do not have to repack, as the OS @@ -1305,13 +1332,21 @@ void GeometryManager::device_update_bvh(Device *device, // Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated // based on that list, which may be ordered differently from the object list. foreach (Geometry *geom, scene->geometry) { - if (!pack_all && !geom->is_modified()) { + /* Make a copy of the pack_flags so the current geometry's flags do not pollute the others'. + */ + PackFlags geom_pack_flags = pack_flags; + + if (geom->is_modified()) { + geom_pack_flags |= PackFlags::PACK_VERTICES; + } + + if (geom_pack_flags == PACK_NONE) { continue; } const pair<int, uint> &info = geometry_to_object_info[geom]; pool.push(function_bind( - &Geometry::pack_primitives, geom, &pack, info.first, info.second, pack_all)); + &Geometry::pack_primitives, geom, &pack, info.first, info.second, geom_pack_flags)); } pool.wait_work(); } @@ -1346,7 +1381,7 @@ void GeometryManager::device_update_bvh(Device *device, dscene->prim_type.steal_data(pack.prim_type); dscene->prim_type.copy_to_device(); } - if (pack.prim_visibility.size() && (dscene->prim_visibility.need_realloc() || has_bvh2_layout)) { + if (pack.prim_visibility.size() && (dscene->prim_visibility.is_modified() || has_bvh2_layout)) { dscene->prim_visibility.steal_data(pack.prim_visibility); dscene->prim_visibility.copy_to_device(); } @@ -1403,24 +1438,46 @@ static void update_device_flags_attribute(uint32_t &device_update_flags, continue; } - if (attr.element == ATTR_ELEMENT_CORNER) { - device_update_flags |= ATTR_UCHAR4_MODIFIED; - } - else if (attr.type == TypeDesc::TypeFloat) { - device_update_flags |= ATTR_FLOAT_MODIFIED; - } - else if (attr.type == TypeFloat2) { - device_update_flags |= ATTR_FLOAT2_MODIFIED; - } - else if (attr.type == TypeDesc::TypeMatrix) { - device_update_flags |= ATTR_FLOAT3_MODIFIED; - } - else if (attr.element != ATTR_ELEMENT_VOXEL) { - device_update_flags |= ATTR_FLOAT3_MODIFIED; + AttrKernelDataType kernel_type = Attribute::kernel_type(attr); + + switch (kernel_type) { + case AttrKernelDataType::FLOAT: { + device_update_flags |= ATTR_FLOAT_MODIFIED; + break; + } + case AttrKernelDataType::FLOAT2: { + device_update_flags |= ATTR_FLOAT2_MODIFIED; + break; + } + case AttrKernelDataType::FLOAT3: { + device_update_flags |= ATTR_FLOAT3_MODIFIED; + break; + } + case AttrKernelDataType::UCHAR4: { + device_update_flags |= ATTR_UCHAR4_MODIFIED; + break; + } } } } +static void update_attribute_realloc_flags(uint32_t &device_update_flags, + const AttributeSet &attributes) +{ + if (attributes.modified(AttrKernelDataType::FLOAT)) { + device_update_flags |= ATTR_FLOAT_NEEDS_REALLOC; + } + if (attributes.modified(AttrKernelDataType::FLOAT2)) { + device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC; + } + if (attributes.modified(AttrKernelDataType::FLOAT3)) { + device_update_flags |= ATTR_FLOAT3_NEEDS_REALLOC; + } + if (attributes.modified(AttrKernelDataType::UCHAR4)) { + device_update_flags |= ATTR_UCHAR4_NEEDS_REALLOC; + } +} + void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) { if (!need_update() && !need_flags_update) { @@ -1443,16 +1500,11 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro foreach (Geometry *geom, scene->geometry) { geom->has_volume = false; - if (geom->attributes.modified) { - device_update_flags |= ATTRS_NEED_REALLOC; - } + update_attribute_realloc_flags(device_update_flags, geom->attributes); if (geom->is_mesh()) { Mesh *mesh = static_cast<Mesh *>(geom); - - if (mesh->subd_attributes.modified) { - device_update_flags |= ATTRS_NEED_REALLOC; - } + update_attribute_realloc_flags(device_update_flags, mesh->subd_attributes); } foreach (Node *node, geom->get_used_shaders()) { @@ -1594,6 +1646,10 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro } } + if ((update_flags & VISIBILITY_MODIFIED) != 0) { + dscene->prim_visibility.tag_modified(); + } + if (device_update_flags & ATTR_FLOAT_NEEDS_REALLOC) { dscene->attributes_map.tag_realloc(); dscene->attributes_float.tag_realloc(); @@ -1920,7 +1976,8 @@ void GeometryManager::device_update(Device *device, * Also update the BVH if the transformations change, we cannot rely on tagging the Geometry * as modified in this case, as we may accumulate displacement if the vertices do not also * change. */ - bool need_update_scene_bvh = (scene->bvh == nullptr || (update_flags & TRANSFORM_MODIFIED) != 0); + bool need_update_scene_bvh = (scene->bvh == nullptr || + (update_flags & (TRANSFORM_MODIFIED | VISIBILITY_MODIFIED)) != 0); { scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { |