Commit: 338fe9e2b5360705b9edd9c526e76dece2477610 Author: Hans Goudey Date: Thu Mar 10 09:37:42 2022 -0600 Branches: master https://developer.blender.org/rB338fe9e2b5360705b9edd9c526e76dece2477610
Cleanup: Reduce duplication in realize instances code Realizing and copying attributes of meshes, curves, and points are very similar processes, but currently the logic is duplicated three times in the realize instances code. This commit combines the implementation for copying generic attributes and creating the result id attribute. The functions for threaded copying and filling should ideally be in some file elsewhere, since they're not just useful here. But it's not clear where they would go yet. Differential Revision: https://developer.blender.org/D14294 =================================================================== M source/blender/geometry/intern/realize_instances.cc =================================================================== diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 94c75e8dbb1..100146bbf0c 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -265,6 +265,81 @@ static void copy_transformed_positions(const Span<float3> src, }); } +static void threaded_copy(const GSpan src, GMutableSpan dst) +{ + BLI_assert(src.size() == dst.size()); + BLI_assert(src.type() == dst.type()); + threading::parallel_for(IndexRange(src.size()), 1024, [&](const IndexRange range) { + src.type().copy_construct_n(src.slice(range).data(), dst.slice(range).data(), range.size()); + }); +} + +static void threaded_fill(const fn::GPointer value, GMutableSpan dst) +{ + BLI_assert(*value.type() == dst.type()); + threading::parallel_for(IndexRange(dst.size()), 1024, [&](const IndexRange range) { + value.type()->fill_construct_n(value.get(), dst.slice(range).data(), range.size()); + }); +} + +static void copy_generic_attributes_to_result( + const Span<std::optional<GVArray_GSpan>> src_attributes, + const AttributeFallbacksArray &attribute_fallbacks, + const OrderedAttributes &ordered_attributes, + const FunctionRef<IndexRange(AttributeDomain)> &range_fn, + MutableSpan<GMutableSpan> dst_attributes) +{ + threading::parallel_for(dst_attributes.index_range(), 10, [&](const IndexRange attribute_range) { + for (const int attribute_index : attribute_range) { + const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; + const IndexRange element_slice = range_fn(domain); + + GMutableSpan dst_span = dst_attributes[attribute_index].slice(element_slice); + if (src_attributes[attribute_index].has_value()) { + threaded_copy(*src_attributes[attribute_index], dst_span); + } + else { + const CPPType &cpp_type = dst_span.type(); + const void *fallback = attribute_fallbacks.array[attribute_index] == nullptr ? + cpp_type.default_value() : + attribute_fallbacks.array[attribute_index]; + threaded_fill({cpp_type, fallback}, dst_span); + } + } + }); +} + +static void create_result_ids(const RealizeInstancesOptions &options, + Span<int> stored_ids, + const int task_id, + MutableSpan<int> dst_ids) +{ + if (options.keep_original_ids) { + if (stored_ids.is_empty()) { + dst_ids.fill(0); + } + else { + dst_ids.copy_from(stored_ids); + } + } + else { + if (stored_ids.is_empty()) { + threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + dst_ids[i] = noise::hash(task_id, i); + } + }); + } + else { + threading::parallel_for(dst_ids.index_range(), 1024, [&](const IndexRange range) { + for (const int i : range) { + dst_ids[i] = noise::hash(task_id, stored_ids[i]); + } + }); + } + } +} + /* -------------------------------------------------------------------- */ /** \name Gather Realize Tasks * \{ */ @@ -595,6 +670,7 @@ static AllPointCloudsInfo preprocess_pointclouds(const GeometrySet &geometry_set static void execute_realize_pointcloud_task(const RealizeInstancesOptions &options, const RealizePointCloudTask &task, + const OrderedAttributes &ordered_attributes, PointCloud &dst_pointcloud, MutableSpan<GMutableSpan> dst_attribute_spans, MutableSpan<int> all_dst_ids) @@ -605,64 +681,25 @@ static void execute_realize_pointcloud_task(const RealizeInstancesOptions &optio const IndexRange point_slice{task.start_index, pointcloud.totpoint}; MutableSpan<float3> dst_positions{(float3 *)dst_pointcloud.co + task.start_index, pointcloud.totpoint}; - MutableSpan<int> dst_ids = all_dst_ids.slice(task.start_index, pointcloud.totpoint); copy_transformed_positions(src_positions, task.transform, dst_positions); /* Create point ids. */ if (!all_dst_ids.is_empty()) { - if (options.keep_original_ids) { - if (pointcloud_info.stored_ids.is_empty()) { - dst_ids.fill(0); - } - else { - dst_ids.copy_from(pointcloud_info.stored_ids); - } - } - else { - threading::parallel_for(IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - if (pointcloud_info.stored_ids.is_empty()) { - for (const int i : range) { - dst_ids[i] = noise::hash(task.id, i); - } - } - else { - for (const int i : range) { - dst_ids[i] = noise::hash(task.id, pointcloud_info.stored_ids[i]); - } - } - }); - } + create_result_ids( + options, pointcloud_info.stored_ids, task.id, all_dst_ids.slice(point_slice)); } - /* Copy generic attributes. */ - threading::parallel_for( - dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) { - for (const int attribute_index : attribute_range) { - GMutableSpan dst_span = dst_attribute_spans[attribute_index].slice(point_slice); - const CPPType &cpp_type = dst_span.type(); - const void *attribute_fallback = task.attribute_fallbacks.array[attribute_index]; - if (pointcloud_info.attributes[attribute_index].has_value()) { - /* Copy attribute from the original point cloud. */ - const GSpan src_span = *pointcloud_info.attributes[attribute_index]; - threading::parallel_for( - IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - cpp_type.copy_construct_n( - src_span.slice(range).data(), dst_span.slice(range).data(), range.size()); - }); - } - else { - if (attribute_fallback == nullptr) { - attribute_fallback = cpp_type.default_value(); - } - /* As the fallback value for the attribute. */ - threading::parallel_for( - IndexRange(pointcloud.totpoint), 1024, [&](const IndexRange range) { - cpp_type.fill_construct_n( - attribute_fallback, dst_span.slice(range).data(), range.size()); - }); - } - } - }); + + copy_generic_attributes_to_result( + pointcloud_info.attributes, + task.attribute_fallbacks, + ordered_attributes, + [&](const AttributeDomain domain) { + BLI_assert(domain == ATTR_DOMAIN_POINT); + UNUSED_VARS_NDEBUG(domain); + return point_slice; + }, + dst_attribute_spans); } static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &options, @@ -710,7 +747,7 @@ static void execute_realize_pointcloud_tasks(const RealizeInstancesOptions &opti for (const int task_index : task_range) { const RealizePointCloudTask &task = tasks[task_index]; execute_realize_pointcloud_task( - options, task, *dst_pointcloud, dst_attribute_spans, point_ids_span); + options, task, ordered_attributes, *dst_pointcloud, dst_attribute_spans, point_ids_span); } }); @@ -842,9 +879,6 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, MutableSpan<MLoop> dst_loops{dst_mesh.mloop + task.start_indices.loop, mesh.totloop}; MutableSpan<MPoly> dst_polys{dst_mesh.mpoly + task.start_indices.poly, mesh.totpoly}; - MutableSpan<int> dst_vertex_ids = all_dst_vertex_ids.slice(task.start_indices.vertex, - mesh.totvert); - const Span<int> material_index_map = mesh_info.material_index_map; threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) { @@ -888,79 +922,34 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options, } } }); - /* Create id attribute. */ + if (!all_dst_vertex_ids.is_empty()) { - if (options.keep_original_ids) { - if (mesh_info.stored_vertex_ids.is_empty()) { - dst_vertex_ids.fill(0); - } - else { - dst_vertex_ids.copy_from(mesh_info.stored_vertex_ids); - } - } - else { - threading::parallel_for(IndexRange(mesh.totvert), 1024, [&](const IndexRange vert_range) { - if (mesh_info.stored_vertex_ids.is_empty()) { - for (const int i : vert_range) { - dst_vertex_ids[i] = noise::hash(task.id, i); - } - } - else { - for (const int i : vert_range) { - const int original_id = mesh_info.stored_vertex_ids[i]; - dst_vertex_ids[i] = noise::hash(task.id, original_id); - } - } - }); - } + create_result_ids(options, + mesh_info.stored_vertex_ids, + task.id, + all_dst_vertex_ids.slice(task.start_indices.vertex, mesh.totvert)); } - /* Copy generic attributes. */ - threading::parallel_for( - dst_attribute_spans.index_range(), 10, [&](const IndexRange attribute_range) { - for (const int attribute_index : attribute_range) { - const AttributeDomain domain = ordered_attributes.kinds[attribute_index].domain; - IndexRange element_slice; - switch (domain) { - case ATTR_DOMAIN_POINT: - element_slice = IndexRange(task.start_indices.vertex, mesh.totvert); - break; - case ATTR_DOMAIN_EDGE: - element_slice = IndexRange(task.start_indices.edge, mesh.totedge); - break; - case ATTR_DOMAIN_CORNER: - element_slice = IndexRange(task.start_indices.loop, mesh.totloop); - break; - case ATTR_DOMAIN_FACE: - element_slice = IndexRange(task.start_indices.poly, mesh.totpoly); - @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
