[Bf-blender-cvs] [9fd2e540ab8] devirtualizer: use in CustomMF_SI_SO

Jacques Lucke noreply at git.blender.org
Sun Apr 10 16:00:28 CEST 2022


Commit: 9fd2e540ab8f27fb98bd583753838d5d0f6f087a
Author: Jacques Lucke
Date:   Sun Apr 10 15:37:26 2022 +0200
Branches: devirtualizer
https://developer.blender.org/rB9fd2e540ab8f27fb98bd583753838d5d0f6f087a

use in CustomMF_SI_SO

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

M	source/blender/functions/FN_multi_function_builder.hh

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

diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index ed587a87695..25dabec8d38 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -10,6 +10,8 @@
 
 #include <functional>
 
+#include "BLI_virtual_array_devirtualize.hh"
+
 #include "FN_multi_function.hh"
 
 namespace blender::fn {
@@ -47,72 +49,23 @@ template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunctio
   template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn)
   {
     return [=](IndexMask mask, const VArray<In1> &in1, MutableSpan<Out1> out1) {
-      if (in1.is_single()) {
-        /* Only evaluate the function once when the input is a single value. */
-        const In1 in1_single = in1.get_internal_single();
-        const Out1 out1_single = element_fn(in1_single);
-        out1.fill_indices(mask, out1_single);
-        return;
-      }
-
-      if (in1.is_span()) {
-        const Span<In1> in1_span = in1.get_internal_span();
-        mask.to_best_mask_type(
-            [&](auto mask) { execute_SI_SO(element_fn, mask, in1_span, out1.data()); });
-        return;
-      }
-
-      /* The input is an unknown virtual array type. To avoid virtual function call overhead for
-       * every element, elements are retrieved and processed in chunks. */
-
-      static constexpr int64_t MaxChunkSize = 32;
-      TypedBuffer<In1, MaxChunkSize> in1_buffer_owner;
-      MutableSpan<In1> in1_buffer{in1_buffer_owner.ptr(), MaxChunkSize};
-
-      const int64_t mask_size = mask.size();
-      for (int64_t chunk_start = 0; chunk_start < mask_size; chunk_start += MaxChunkSize) {
-        const int64_t chunk_size = std::min(mask_size - chunk_start, MaxChunkSize);
-        const IndexMask sliced_mask = mask.slice(chunk_start, chunk_size);
-
-        /* Load input from the virtual array. */
-        MutableSpan<In1> in1_chunk = in1_buffer.take_front(chunk_size);
-        in1.materialize_compressed_to_uninitialized(sliced_mask, in1_chunk);
-
-        if (sliced_mask.is_range()) {
-          execute_SI_SO(
-              element_fn, IndexRange(chunk_size), in1_chunk, out1.data() + sliced_mask[0]);
-        }
-        else {
-          execute_SI_SO_compressed(element_fn, sliced_mask, in1_chunk, out1.data());
+      auto fn = [&](auto in_indices, auto out_indices, auto in1, Out1 *out1) {
+        BLI_assert(in_indices.size() == out_indices.size());
+        for (const int64_t i : IndexRange(in_indices.size())) {
+          const int64_t in_index = in_indices[i];
+          const int64_t out_index = out_indices[i];
+          new (out1 + out_index) Out1(element_fn(in1[in_index]));
         }
-        destruct_n(in1_chunk.data(), chunk_size);
+      };
+
+      ArrayDevirtualizer<decltype(fn), SingleInputTag<In1>, SingleOutputTag<Out1>> devirtualizer{
+          fn, &mask, &in1, &out1};
+      if (!devirtualizer.try_execute_devirtualized()) {
+        devirtualizer.execute_materialized();
       }
     };
   }
 
-  template<typename ElementFuncT, typename MaskT, typename In1Array>
-  BLI_NOINLINE static void execute_SI_SO(const ElementFuncT &element_fn,
-                                         MaskT mask,
-                                         const In1Array &in1,
-                                         Out1 *__restrict r_out)
-  {
-    for (const int64_t i : mask) {
-      new (r_out + i) Out1(element_fn(in1[i]));
-    }
-  }
-
-  /** Expects the input array to be "compressed", i.e. there are no gaps between the elements. */
-  template<typename ElementFuncT, typename MaskT, typename In1Array>
-  BLI_NOINLINE static void execute_SI_SO_compressed(const ElementFuncT &element_fn,
-                                                    MaskT mask,
-                                                    const In1Array &in1,
-                                                    Out1 *__restrict r_out)
-  {
-    for (const int64_t i : IndexRange(mask.size())) {
-      new (r_out + mask[i]) Out1(element_fn(in1[i]));
-    }
-  }
-
   void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override
   {
     const VArray<In1> &in1 = params.readonly_single_input<In1>(0);



More information about the Bf-blender-cvs mailing list