From 10353b3d69ff1cfe898b7d2e9452b9a1aaa7c7e8 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 10 Sep 2025 15:45:56 +0200 Subject: [PATCH] BLI: reduce binary size for non-performance sensitive virtual arrays This adds a `VArray::from_std_func` next to the existing `VArray::from_func`. It does almost the same but inserts some type erasure by using `std::function` which avoids the need to instantiate the full virtual array. This has is a bit slower at run-time, but in practice there are some cases where it doesn't matter. Currently, this patch reduces binary size by ~35kb. Not too much, but still good or such a simple change. Pull Request: https://projects.blender.org/blender/blender/pulls/146011 --- source/blender/blenlib/BLI_virtual_array.hh | 9 +++++++++ .../sculpt_paint/grease_pencil_draw_ops.cc | 12 ++++++------ .../spreadsheet_data_source_geometry.cc | 19 ++++++++++--------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 5544db55aea..26c9ebc901d 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -913,6 +913,15 @@ template class VArray : public VArrayCommon { return VArray::from>(size, std::move(get_func)); } + /** + * Same as #from_func, but uses a std::function instead of a template. This is slower, but + * requires less code generation. Therefore this should be used in non-performance critical code. + */ + static VArray from_std_func(const int64_t size, std::function get_func) + { + return VArray::from_func(size, get_func); + } + /** * Construct a new virtual array for an existing span with a mapping function. This does not take * ownership of the span. diff --git a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc index 5c7a030617b..895e6c92632 100644 --- a/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc +++ b/source/blender/editors/sculpt_paint/grease_pencil_draw_ops.cc @@ -1198,27 +1198,27 @@ static VArray get_fill_boundary_layers(const GreasePencil &grease_pencil, switch (fill_layer_mode) { case GP_FILL_GPLMODE_ACTIVE: - return VArray::from_func(all_layers.size(), [active_layer_index](const int index) { + return VArray::from_std_func(all_layers.size(), [active_layer_index](const int index) { return index != active_layer_index; }); case GP_FILL_GPLMODE_ABOVE: - return VArray::from_func(all_layers.size(), [active_layer_index](const int index) { + return VArray::from_std_func(all_layers.size(), [active_layer_index](const int index) { return index != active_layer_index + 1; }); case GP_FILL_GPLMODE_BELOW: - return VArray::from_func(all_layers.size(), [active_layer_index](const int index) { + return VArray::from_std_func(all_layers.size(), [active_layer_index](const int index) { return index != active_layer_index - 1; }); case GP_FILL_GPLMODE_ALL_ABOVE: - return VArray::from_func(all_layers.size(), [active_layer_index](const int index) { + return VArray::from_std_func(all_layers.size(), [active_layer_index](const int index) { return index <= active_layer_index; }); case GP_FILL_GPLMODE_ALL_BELOW: - return VArray::from_func(all_layers.size(), [active_layer_index](const int index) { + return VArray::from_std_func(all_layers.size(), [active_layer_index](const int index) { return index >= active_layer_index; }); case GP_FILL_GPLMODE_VISIBLE: - return VArray::from_func(all_layers.size(), [grease_pencil](const int index) { + return VArray::from_std_func(all_layers.size(), [grease_pencil](const int index) { return !grease_pencil.layers()[index]->is_visible(); }); } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index 3fd5691627b..00556c92dde 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -139,7 +139,7 @@ static std::unique_ptr build_mesh_debug_columns(const Mesh &mesh, if (name == "Corner Size") { const OffsetIndices faces = mesh.faces(); return std::make_unique( - name, VArray::from_func(faces.size(), [faces](int64_t index) { + name, VArray::from_std_func(faces.size(), [faces](int64_t index) { return faces[index].size(); })); } @@ -244,7 +244,7 @@ std::unique_ptr GeometryDataSource::get_column_values( Span references = instances->references(); return std::make_unique( column_id.name, - VArray::from_func( + VArray::from_std_func( domain_num, [reference_handles, references](int64_t index) { return references[reference_handles[index]]; })); @@ -252,19 +252,19 @@ std::unique_ptr GeometryDataSource::get_column_values( Span transforms = instances->transforms(); if (STREQ(column_id.name, "Position")) { return std::make_unique( - column_id.name, VArray::from_func(domain_num, [transforms](int64_t index) { + column_id.name, VArray::from_std_func(domain_num, [transforms](int64_t index) { return transforms[index].location(); })); } if (STREQ(column_id.name, "Rotation")) { return std::make_unique( - column_id.name, VArray::from_func(domain_num, [transforms](int64_t index) { + column_id.name, VArray::from_std_func(domain_num, [transforms](int64_t index) { return float3(math::to_euler(math::normalize(transforms[index]))); })); } if (STREQ(column_id.name, "Scale")) { return std::make_unique( - column_id.name, VArray::from_func(domain_num, [transforms](int64_t index) { + column_id.name, VArray::from_std_func(domain_num, [transforms](int64_t index) { return math::to_scale(transforms[index]); })); } @@ -277,7 +277,8 @@ std::unique_ptr GeometryDataSource::get_column_values( if (domain_ == bke::AttrDomain::Layer && STREQ(column_id.name, "Name")) { const Span layers = grease_pencil->layers(); return std::make_unique( - column_id.name, VArray::from_func(domain_num, [layers](int64_t index) { + column_id.name, + VArray::from_std_func(domain_num, [layers](int64_t index) { StringRefNull name = layers[index]->name(); if (name.is_empty()) { name = IFACE_("(Layer)"); @@ -562,14 +563,14 @@ std::unique_ptr VolumeDataSource::get_column_values( const int size = this->tot_rows(); if (STREQ(column_id.name, "Grid Name")) { return std::make_unique( - IFACE_("Grid Name"), VArray::from_func(size, [volume](int64_t index) { + IFACE_("Grid Name"), VArray::from_std_func(size, [volume](int64_t index) { const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index); return volume_grid->name(); })); } if (STREQ(column_id.name, "Data Type")) { return std::make_unique( - IFACE_("Data Type"), VArray::from_func(size, [volume](int64_t index) { + IFACE_("Data Type"), VArray::from_std_func(size, [volume](int64_t index) { const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index); const VolumeGridType type = volume_grid->grid_type(); const char *name = nullptr; @@ -579,7 +580,7 @@ std::unique_ptr VolumeDataSource::get_column_values( } if (STREQ(column_id.name, "Class")) { return std::make_unique( - IFACE_("Class"), VArray::from_func(size, [volume](int64_t index) { + IFACE_("Class"), VArray::from_std_func(size, [volume](int64_t index) { const bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, index); openvdb::GridClass grid_class = volume_grid->grid_class(); if (grid_class == openvdb::GridClass::GRID_FOG_VOLUME) {