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
This commit is contained in:
Jacques Lucke
2025-09-10 15:45:56 +02:00
parent 5c2f06bfc4
commit 10353b3d69
3 changed files with 25 additions and 15 deletions

View File

@@ -913,6 +913,15 @@ template<typename T> class VArray : public VArrayCommon<T> {
return VArray::from<VArrayImpl_For_Func<T, decltype(get_func)>>(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<T(int64_t index)> 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.

View File

@@ -1198,27 +1198,27 @@ static VArray<bool> get_fill_boundary_layers(const GreasePencil &grease_pencil,
switch (fill_layer_mode) {
case GP_FILL_GPLMODE_ACTIVE:
return VArray<bool>::from_func(all_layers.size(), [active_layer_index](const int index) {
return VArray<bool>::from_std_func(all_layers.size(), [active_layer_index](const int index) {
return index != active_layer_index;
});
case GP_FILL_GPLMODE_ABOVE:
return VArray<bool>::from_func(all_layers.size(), [active_layer_index](const int index) {
return VArray<bool>::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<bool>::from_func(all_layers.size(), [active_layer_index](const int index) {
return VArray<bool>::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<bool>::from_func(all_layers.size(), [active_layer_index](const int index) {
return VArray<bool>::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<bool>::from_func(all_layers.size(), [active_layer_index](const int index) {
return VArray<bool>::from_std_func(all_layers.size(), [active_layer_index](const int index) {
return index >= active_layer_index;
});
case GP_FILL_GPLMODE_VISIBLE:
return VArray<bool>::from_func(all_layers.size(), [grease_pencil](const int index) {
return VArray<bool>::from_std_func(all_layers.size(), [grease_pencil](const int index) {
return !grease_pencil.layers()[index]->is_visible();
});
}

View File

@@ -139,7 +139,7 @@ static std::unique_ptr<ColumnValues> build_mesh_debug_columns(const Mesh &mesh,
if (name == "Corner Size") {
const OffsetIndices faces = mesh.faces();
return std::make_unique<ColumnValues>(
name, VArray<int>::from_func(faces.size(), [faces](int64_t index) {
name, VArray<int>::from_std_func(faces.size(), [faces](int64_t index) {
return faces[index].size();
}));
}
@@ -244,7 +244,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
Span<bke::InstanceReference> references = instances->references();
return std::make_unique<ColumnValues>(
column_id.name,
VArray<bke::InstanceReference>::from_func(
VArray<bke::InstanceReference>::from_std_func(
domain_num, [reference_handles, references](int64_t index) {
return references[reference_handles[index]];
}));
@@ -252,19 +252,19 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
Span<float4x4> transforms = instances->transforms();
if (STREQ(column_id.name, "Position")) {
return std::make_unique<ColumnValues>(
column_id.name, VArray<float3>::from_func(domain_num, [transforms](int64_t index) {
column_id.name, VArray<float3>::from_std_func(domain_num, [transforms](int64_t index) {
return transforms[index].location();
}));
}
if (STREQ(column_id.name, "Rotation")) {
return std::make_unique<ColumnValues>(
column_id.name, VArray<float3>::from_func(domain_num, [transforms](int64_t index) {
column_id.name, VArray<float3>::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<ColumnValues>(
column_id.name, VArray<float3>::from_func(domain_num, [transforms](int64_t index) {
column_id.name, VArray<float3>::from_std_func(domain_num, [transforms](int64_t index) {
return math::to_scale<true>(transforms[index]);
}));
}
@@ -277,7 +277,8 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values(
if (domain_ == bke::AttrDomain::Layer && STREQ(column_id.name, "Name")) {
const Span<const bke::greasepencil::Layer *> layers = grease_pencil->layers();
return std::make_unique<ColumnValues>(
column_id.name, VArray<std::string>::from_func(domain_num, [layers](int64_t index) {
column_id.name,
VArray<std::string>::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<ColumnValues> VolumeDataSource::get_column_values(
const int size = this->tot_rows();
if (STREQ(column_id.name, "Grid Name")) {
return std::make_unique<ColumnValues>(
IFACE_("Grid Name"), VArray<std::string>::from_func(size, [volume](int64_t index) {
IFACE_("Grid Name"), VArray<std::string>::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<ColumnValues>(
IFACE_("Data Type"), VArray<std::string>::from_func(size, [volume](int64_t index) {
IFACE_("Data Type"), VArray<std::string>::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<ColumnValues> VolumeDataSource::get_column_values(
}
if (STREQ(column_id.name, "Class")) {
return std::make_unique<ColumnValues>(
IFACE_("Class"), VArray<std::string>::from_func(size, [volume](int64_t index) {
IFACE_("Class"), VArray<std::string>::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) {