[Bf-blender-cvs] [b5105085139] master: Geometry Nodes: optimize Sample Index node with constant index

Jacques Lucke noreply at git.blender.org
Tue Jan 17 13:30:03 CET 2023


Commit: b5105085139227a713f154446ff6a3255cb8be99
Author: Jacques Lucke
Date:   Tue Jan 17 13:29:55 2023 +0100
Branches: master
https://developer.blender.org/rBb5105085139227a713f154446ff6a3255cb8be99

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.

===================================================================

M	source/blender/nodes/geometry/nodes/node_geo_sample_index.cc

===================================================================

diff --git a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc
index 4f6062cb553..850b2cfdd66 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_sample_index.cc
@@ -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



More information about the Bf-blender-cvs mailing list