[Bf-blender-cvs] [95288eba596] temp-geometry-nodes-fields: improve field evaluator and add geometry context

Jacques Lucke noreply at git.blender.org
Thu Sep 2 12:48:09 CEST 2021


Commit: 95288eba5965ce92a04864040ff088f40c18ada2
Author: Jacques Lucke
Date:   Thu Sep 2 12:41:19 2021 +0200
Branches: temp-geometry-nodes-fields
https://developer.blender.org/rB95288eba5965ce92a04864040ff088f40c18ada2

improve field evaluator and add geometry context

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

M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenkernel/intern/customdata.c
M	source/blender/functions/FN_field.hh
M	source/blender/functions/intern/field.cc
M	source/blender/nodes/NOD_geometry_exec.hh

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

diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 45e8ab92e41..da758669659 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -35,6 +35,8 @@
 #include "BKE_attribute_access.hh"
 #include "BKE_geometry_set.h"
 
+#include "FN_field.hh"
+
 struct Collection;
 struct Curve;
 struct CurveEval;
@@ -581,3 +583,44 @@ class VolumeComponent : public GeometryComponent {
 
   static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
 };
+
+namespace blender::bke {
+
+class GeometryComponentFieldContext : public fn::FieldContext {
+ private:
+  const GeometryComponent &component_;
+  const AttributeDomain domain_;
+
+ public:
+  GeometryComponentFieldContext(const GeometryComponent &component, const AttributeDomain domain)
+      : component_(component), domain_(domain)
+  {
+  }
+
+  const GeometryComponent &geometry_component() const
+  {
+    return component_;
+  }
+
+  AttributeDomain domain() const
+  {
+    return domain_;
+  }
+};
+
+class AttributeContextFieldSource : public fn::ContextFieldSource {
+ private:
+  std::string name_;
+
+ public:
+  AttributeContextFieldSource(std::string name, const CPPType &type)
+      : fn::ContextFieldSource(type, name), name_(std::move(name))
+  {
+  }
+
+  const GVArray *try_get_varray_for_context(const fn::FieldContext &context,
+                                            IndexMask mask,
+                                            ResourceScope &scope) const override;
+};
+
+}  // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 941bfebcc60..bf3756b7bcf 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -1300,3 +1300,21 @@ blender::bke::OutputAttribute GeometryComponent::attribute_try_get_for_output_on
 {
   return create_output_attribute(*this, attribute_id, domain, data_type, true, nullptr);
 }
+
+namespace blender::bke {
+
+const GVArray *AttributeContextFieldSource::try_get_varray_for_context(
+    const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const
+{
+  if (const GeometryComponentFieldContext *geometry_context =
+          dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
+    const GeometryComponent &component = geometry_context->geometry_component();
+    const AttributeDomain domain = geometry_context->domain();
+    const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
+    GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type);
+    return scope.add(std::move(attribute), __func__);
+  }
+  return nullptr;
+}
+
+}  // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index a86d0a608d6..311039bac24 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2848,7 +2848,7 @@ void *CustomData_duplicate_referenced_layer_named(CustomData *data,
 }
 
 void *CustomData_duplicate_referenced_layer_anonymous(CustomData *data,
-                                                      const int type,
+                                                      const int UNUSED(type),
                                                       const AnonymousAttributeID *anonymous_id,
                                                       const int totelem)
 {
@@ -3564,7 +3564,6 @@ bool CustomData_bmesh_merge(const CustomData *source,
                             BMesh *bm,
                             const char htype)
 {
-
   if (CustomData_number_of_layers_typemask(source, mask) == 0) {
     return false;
   }
@@ -4813,7 +4812,6 @@ static void copy_bit_flag(void *dst, const void *src, const size_t data_size, co
     *((_type *)(_dst)) |= _val; \
   } \
   (void)0
-
   switch (data_size) {
     case 1:
       COPY_BIT_FLAG(uint8_t, dst, src, flag);
diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh
index 76ffb0225ab..744345fd339 100644
--- a/source/blender/functions/FN_field.hh
+++ b/source/blender/functions/FN_field.hh
@@ -185,9 +185,15 @@ class OperationFieldSource : public FieldSource {
   }
 };
 
+class ContextFieldSource;
+
 class FieldContext {
  public:
   ~FieldContext() = default;
+
+  virtual const GVArray *try_get_varray_for_context(const ContextFieldSource &context_source,
+                                                    IndexMask mask,
+                                                    ResourceScope &scope) const;
 };
 
 class ContextFieldSource : public FieldSource {
@@ -218,6 +224,7 @@ class ContextFieldSource : public FieldSource {
   const CPPType &cpp_type_of_output_index(int output_index) const override
   {
     BLI_assert(output_index == 0);
+    UNUSED_VARS_NDEBUG(output_index);
     return *type_;
   }
 
@@ -255,39 +262,20 @@ template<typename T> Field<T> make_constant_field(T value)
   return Field<T>{GField{std::move(operation), 0}};
 }
 
-class FieldEvaluator;
-
-class GFieldOutputHandle {
- protected:
-  FieldEvaluator *evaluator_;
-  int field_index_;
-
- public:
-  GFieldOutputHandle(FieldEvaluator &evaluator, int field_index)
-      : evaluator_(&evaluator), field_index_(field_index)
-  {
-  }
-
-  const GVArray &get();
-};
-
-template<typename T> class FieldOutputHandle : GFieldOutputHandle {
- public:
-  explicit FieldOutputHandle(const GFieldOutputHandle &other) : GFieldOutputHandle(other)
-  {
-  }
-
-  const VArray<T> &get();
-};
-
 class FieldEvaluator : NonMovable, NonCopyable {
  private:
+  struct OutputPointerInfo {
+    void *dst = nullptr;
+    void (*set)(void *dst, const GVArray &varray, ResourceScope &scope) = nullptr;
+  };
+
   ResourceScope scope_;
   const FieldContext &context_;
   const IndexMask mask_;
   Vector<GField> fields_to_evaluate_;
   Vector<GVMutableArray *> dst_hints_;
   Vector<const GVArray *> evaluated_varrays_;
+  Vector<OutputPointerInfo> output_pointer_infos_;
   bool is_evaluated_ = false;
 
  public:
@@ -297,24 +285,56 @@ class FieldEvaluator : NonMovable, NonCopyable {
   {
   }
 
-  GFieldOutputHandle add(GField field, GVMutableArray *dst_hint = nullptr)
+  /**
+   * \param field: Field to add to the evaluator.
+   * \param dst: Mutable virtual array that the evaluated result for this field is be written into.
+   */
+  int add_with_destination(GField field, GVMutableArray &dst)
   {
     const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
-    dst_hints_.append(dst_hint);
-    return GFieldOutputHandle(*this, field_index);
+    dst_hints_.append(&dst);
+    output_pointer_infos_.append({});
+    return field_index;
   }
 
-  template<typename T>
-  FieldOutputHandle<T> add(Field<T> field, VMutableArray<T> *dst_hint = nullptr)
+  /** Same as above but typed. */
+  template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst)
   {
-    GVMutableArray *generic_dst_hint = nullptr;
-    if (dst_hint != nullptr) {
-      generic_dst_hint = &scope_.construct<GVMutableArray_For_VMutableArray<T>>(__func__,
-                                                                                *dst_hint);
-    }
-    return FieldOutputHandle<T>(this->add(GField(std::move(field)), generic_dst_hint));
+    GVMutableArray &generic_dst_hint = scope_.construct<GVMutableArray_For_VMutableArray<T>>(
+        __func__, dst);
+    return this->add_with_destination(GField(std::move(field)), generic_dst_hint);
   }
 
+  /**
+   * \param field: Field to add to the evaluator.
+   * \param varray_ptr: Once #evaluate is called, the resulting virtual array will be will be
+   *   assigned to the given position.
+   */
+  template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr)
+  {
+    const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
+    dst_hints_.append(nullptr);
+    output_pointer_infos_.append(OutputPointerInfo{
+        varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) {
+          *(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(__func__, varray);
+        }});
+    return field_index;
+  }
+
+  /**
+   * \return Index of the field in the evaluator. Can be used in the #get_evaluated methods.
+   */
+  int add(GField field)
+  {
+    const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
+    dst_hints_.append(nullptr);
+    output_pointer_infos_.append({});
+    return field_index;
+  }
+
+  /**
+   * Evaluate all fields on the evaluator. This can only be called once.
+   */
   void evaluate()
   {
     BLI_assert_msg(!is_evaluated_, "Cannot evaluate twice.");
@@ -323,39 +343,28 @@ class FieldEvaluator : NonMovable, NonCopyable {
       fields[i] = &fields_to_evaluate_[i];
     }
     evaluated_varrays_ = evaluate_fields(scope_, fields, mask_, context_, dst_hints_);
+    BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size());
+    for (const int i : fields_to_evaluate_.index_range()) {
+      OutputPointerInfo &info = output_pointer_infos_[i];
+      if (info.dst != nullptr) {
+        info.set(info.dst, *evaluated_varrays_[i], scope_);
+      }
+    }
     is_evaluated_ = true;
   }
 
-  const GVArray &get(const int field_index) const
+  const GVArray &get_evaluated(const int field_index) const
   {
     BLI_assert(is_evaluated_);
     return *evaluated_varrays_[field_index];
   }
 
-  template<typename T> const VArray<T> &get(const int field_index)
+  template<typename T> const VArray<T> &get_evaluated(const int field_index)
   {
-    const GVArray &varray = this->get(field_index);
+    const GVArray &varray = this->get_evaluated(field_index);
     GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(__func__, varray);
     return *typed_varray;
   }
 };
 
-/* --------------------------------------------------------------------
- * GFieldOutputHandle inline methods.
- */
-
-inline const GVArray &GFieldOutputHandle::get()
-{
-  return evaluator_->get(field_index_);
-}
-
-/* -----

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list