[Bf-blender-cvs] [379344b6363] temp-geometry-nodes-expandable-geometry-socket-prototype: support function nodes on arrays

Jacques Lucke noreply at git.blender.org
Mon Aug 2 15:50:48 CEST 2021


Commit: 379344b6363457e0d793efc6cd4adc8a8d8ecab9
Author: Jacques Lucke
Date:   Mon Aug 2 15:04:02 2021 +0200
Branches: temp-geometry-nodes-expandable-geometry-socket-prototype
https://developer.blender.org/rB379344b6363457e0d793efc6cd4adc8a8d8ecab9

support function nodes on arrays

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

M	source/blender/functions/FN_array_cpp_type.hh
M	source/blender/functions/FN_generic_pointer.hh
M	source/blender/functions/FN_generic_virtual_array.hh
M	source/blender/modifiers/intern/MOD_nodes_evaluator.cc

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

diff --git a/source/blender/functions/FN_array_cpp_type.hh b/source/blender/functions/FN_array_cpp_type.hh
index 181ea543a70..9c1af038814 100644
--- a/source/blender/functions/FN_array_cpp_type.hh
+++ b/source/blender/functions/FN_array_cpp_type.hh
@@ -19,6 +19,7 @@
 #include "BLI_array.hh"
 
 #include "FN_cpp_type.hh"
+#include "FN_generic_span.hh"
 
 namespace blender::fn {
 
@@ -28,6 +29,8 @@ template<typename T> struct ArrayCPPTypeParam {
 class ArrayCPPType : public CPPType {
  private:
   const CPPType &element_type_;
+  GSpan (*get_span_)(const void *value);
+  void (*construct_uninitialized_)(void *r_value, int64_t size);
 
  public:
   template<typename ElementT, int64_t InlineBufferCapacity, typename Allocator>
@@ -38,6 +41,36 @@ class ArrayCPPType : public CPPType {
             debug_name),
         element_type_(CPPType::get<ElementT>())
   {
+    using ArrayT = Array<ElementT, InlineBufferCapacity, Allocator>;
+    get_span_ = [](const void *value) {
+      Span<ElementT> span = *(const ArrayT *)value;
+      return GSpan(span);
+    };
+    construct_uninitialized_ = [](void *r_value, const int64_t size) {
+      new (r_value) ArrayT(size, NoInitialization());
+    };
+  }
+
+  int64_t array_size(const void *value) const
+  {
+    return get_span_(value).size();
+  }
+
+  GSpan array_span(const void *value) const
+  {
+    return get_span_(value);
+  }
+
+  GMutableSpan array_span(void *value) const
+  {
+    GSpan span = get_span_(value);
+    return GMutableSpan(span.type(), (void *)span.data(), span.size());
+  }
+
+  GMutableSpan array_construct_uninitialized(void *r_value, const int64_t size) const
+  {
+    construct_uninitialized_(r_value, size);
+    return this->array_span(r_value);
   }
 };
 
diff --git a/source/blender/functions/FN_generic_pointer.hh b/source/blender/functions/FN_generic_pointer.hh
index c65c42f26c9..746fd0a916a 100644
--- a/source/blender/functions/FN_generic_pointer.hh
+++ b/source/blender/functions/FN_generic_pointer.hh
@@ -41,7 +41,8 @@ class GMutablePointer {
   {
   }
 
-  template<typename T> GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data)
+  template<typename T, typename std::enable_if_t<!std::is_void_v<T>> * = nullptr>
+  GMutablePointer(T *data) : GMutablePointer(&CPPType::get<T>(), data)
   {
   }
 
diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh
index c9398ceb547..30e0df511db 100644
--- a/source/blender/functions/FN_generic_virtual_array.hh
+++ b/source/blender/functions/FN_generic_virtual_array.hh
@@ -588,6 +588,32 @@ template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableAr
   }
 };
 
+class GVArray_For_RepeatedGSpan : public GVArray {
+ private:
+  GSpan span_;
+  const void *default_value_;
+
+ public:
+  GVArray_For_RepeatedGSpan(int64_t size, GSpan span, const void *default_value = nullptr)
+      : GVArray(span.type(), size),
+        span_(span),
+        default_value_(default_value ? default_value : span.type().default_value())
+  {
+  }
+
+ private:
+  void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
+  {
+    if (span_.is_empty()) {
+      type_->copy_construct(default_value_, r_value);
+    }
+    else {
+      const int64_t repeated_index = index % span_.size();
+      type_->copy_construct(span_[repeated_index], r_value);
+    }
+  }
+};
+
 /* A generic version of VArray_Span. */
 class GVArray_GSpan : public GSpan {
  private:
diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
index 2157092d639..98c3943cc33 100644
--- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
+++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc
@@ -21,6 +21,7 @@
 
 #include "DEG_depsgraph_query.h"
 
+#include "FN_array_cpp_type.hh"
 #include "FN_generic_value_map.hh"
 #include "FN_multi_function.hh"
 
@@ -32,6 +33,7 @@
 
 namespace blender::modifiers::geometry_nodes {
 
+using fn::ArrayCPPType;
 using fn::CPPType;
 using fn::GValueMap;
 using nodes::GeoNodeExecParams;
@@ -858,23 +860,45 @@ class GeometryNodesEvaluator {
                                    const MultiFunction &fn,
                                    NodeState &node_state)
   {
+    /* Compute output array length. */
+    int output_size = 0;
+    for (const int i : node->inputs().index_range()) {
+      const InputSocketRef &socket_ref = node->input(i);
+      if (!socket_ref.is_available()) {
+        continue;
+      }
+      BLI_assert(!socket_ref.is_multi_input_socket());
+      InputState &input_state = node_state.inputs[i];
+      BLI_assert(input_state.was_ready_for_execution);
+      SingleInputValue &single_value = *input_state.value.single;
+      BLI_assert(single_value.value != nullptr);
+      const ArrayCPPType *array_cpp_type = dynamic_cast<const ArrayCPPType *>(input_state.type);
+      BLI_assert(array_cpp_type != nullptr);
+      const int input_size = array_cpp_type->array_size(single_value.value);
+      output_size = std::max(output_size, input_size);
+    }
+
     MFContextBuilder fn_context;
-    MFParamsBuilder fn_params{fn, 1};
+    MFParamsBuilder fn_params{fn, output_size};
     LinearAllocator<> &allocator = local_allocators_.local();
 
+    Vector<std::unique_ptr<fn::GVArray>> input_varrays;
+
     /* Prepare the inputs for the multi function. */
     for (const int i : node->inputs().index_range()) {
       const InputSocketRef &socket_ref = node->input(i);
       if (!socket_ref.is_available()) {
         continue;
       }
-      BLI_assert(!socket_ref.is_multi_input_socket());
       InputState &input_state = node_state.inputs[i];
-      BLI_assert(input_state.was_ready_for_execution);
       SingleInputValue &single_value = *input_state.value.single;
-      BLI_assert(single_value.value != nullptr);
-      fn_params.add_readonly_single_input(GPointer{*input_state.type, single_value.value});
+      const ArrayCPPType *array_cpp_type = dynamic_cast<const ArrayCPPType *>(input_state.type);
+      GSpan span = array_cpp_type->array_span(single_value.value);
+      auto varray = std::make_unique<fn::GVArray_For_RepeatedGSpan>(output_size, span);
+      fn_params.add_readonly_single_input(*varray);
+      input_varrays.append(std::move(varray));
     }
+
     /* Prepare the outputs for the multi function. */
     Vector<GMutablePointer> outputs;
     for (const int i : node->outputs().index_range()) {
@@ -882,13 +906,16 @@ class GeometryNodesEvaluator {
       if (!socket_ref.is_available()) {
         continue;
       }
-      const CPPType &type = *get_socket_cpp_type(socket_ref);
-      void *buffer = allocator.allocate(type.size(), type.alignment());
-      fn_params.add_uninitialized_single_output(GMutableSpan{type, buffer, 1});
+      const ArrayCPPType *type = dynamic_cast<const ArrayCPPType *>(
+          get_socket_cpp_type(socket_ref));
+      BLI_assert(type != nullptr);
+      void *buffer = allocator.allocate(type->size(), type->alignment());
+      GMutableSpan span = type->array_construct_uninitialized(buffer, output_size);
+      fn_params.add_uninitialized_single_output(span);
       outputs.append({type, buffer});
     }
 
-    fn.call(IndexRange(1), fn_params, fn_context);
+    fn.call(IndexRange(output_size), fn_params, fn_context);
 
     /* Forward the computed outputs. */
     int output_index = 0;



More information about the Bf-blender-cvs mailing list