Geometry Nodes: optimize Sample Index node with constant index
Previously, the node would always evaluate the input field on the entire geometry domain. This is good when most indices will be accessed afterwards. However, it is quite a bad when only a single index is used. Now the field is only evaluated for that one index.
This commit is contained in:
parent
03fab057f1
commit
b510508513
Notes:
blender-bot
2023-02-14 08:06:38 +01:00
Referenced by commit 34326fec02
, Fix: sample index node outputs default value
|
@ -299,12 +299,39 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
const eCustomDataType data_type = eCustomDataType(storage.data_type);
|
||||
const eAttrDomain domain = eAttrDomain(storage.domain);
|
||||
|
||||
auto fn = std::make_shared<SampleIndexFunction>(std::move(geometry),
|
||||
get_input_attribute_field(params, data_type),
|
||||
domain,
|
||||
bool(storage.clamp));
|
||||
auto op = FieldOperation::Create(std::move(fn), {params.extract_input<Field<int>>("Index")});
|
||||
output_attribute_field(params, GField(std::move(op)));
|
||||
GField value_field = get_input_attribute_field(params, data_type);
|
||||
ValueOrField<int> index_value_or_field = params.extract_input<ValueOrField<int>>("Index");
|
||||
const CPPType &cpp_type = value_field.cpp_type();
|
||||
|
||||
GField output_field;
|
||||
if (index_value_or_field.is_field()) {
|
||||
/* If the index is a field, the output has to be a field that still depends on the input. */
|
||||
auto fn = std::make_shared<SampleIndexFunction>(
|
||||
std::move(geometry), std::move(value_field), domain, bool(storage.clamp));
|
||||
auto op = FieldOperation::Create(std::move(fn), {index_value_or_field.as_field()});
|
||||
output_field = GField(std::move(op));
|
||||
}
|
||||
else if (const GeometryComponent *component = find_source_component(geometry, domain)) {
|
||||
/* Optimization for the case when the index is a single value. Here only that one index has to
|
||||
* be evaluated. */
|
||||
const int index = index_value_or_field.as_value();
|
||||
const IndexMask mask = IndexRange(index, 1);
|
||||
bke::GeometryFieldContext geometry_context(*component, domain);
|
||||
FieldEvaluator evaluator(geometry_context, &mask);
|
||||
evaluator.add(value_field);
|
||||
evaluator.evaluate();
|
||||
const GVArray &data = evaluator.get_evaluated(0);
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(cpp_type, buffer);
|
||||
data.get_to_uninitialized(index, buffer);
|
||||
output_field = fn::make_constant_field(cpp_type, cpp_type.default_value());
|
||||
cpp_type.destruct(buffer);
|
||||
}
|
||||
else {
|
||||
/* Output default value if there is no geometry. */
|
||||
output_field = fn::make_constant_field(cpp_type, cpp_type.default_value());
|
||||
}
|
||||
|
||||
output_attribute_field(params, std::move(output_field));
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_geo_sample_index_cc
|
||||
|
|
Loading…
Reference in New Issue