[Bf-blender-cvs] [0264b27c5e0] devirtualizer: progress

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


Commit: 0264b27c5e033b868665368a8b617ca39611784f
Author: Jacques Lucke
Date:   Sun Apr 10 14:27:52 2022 +0200
Branches: devirtualizer
https://developer.blender.org/rB0264b27c5e033b868665368a8b617ca39611784f

progress

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

M	source/blender/blenlib/BLI_virtual_array_devirtualize.hh
M	source/blender/blenlib/tests/BLI_virtual_array_test.cc

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

diff --git a/source/blender/blenlib/BLI_virtual_array_devirtualize.hh b/source/blender/blenlib/BLI_virtual_array_devirtualize.hh
index 26dd99b029a..8c1213e3c0b 100644
--- a/source/blender/blenlib/BLI_virtual_array_devirtualize.hh
+++ b/source/blender/blenlib/BLI_virtual_array_devirtualize.hh
@@ -30,10 +30,11 @@ template<typename T> struct ParamType<SingleOutputTag<T>> {
   using type = MutableSpan<T>;
 };
 
-enum class DevirtualizeMode {
-  None,
-  Span,
-  Single,
+struct DevirtualizeNone {
+};
+struct DevirtualizeSpan {
+};
+struct DevirtualizeSingle {
 };
 
 template<typename Fn, typename... Args> class ArrayDevirtualizer {
@@ -47,6 +48,8 @@ template<typename Fn, typename... Args> class ArrayDevirtualizer {
   std::array<bool, sizeof...(Args)> varray_is_span_;
   std::array<bool, sizeof...(Args)> varray_is_single_;
 
+  bool executed_ = false;
+
  public:
   ArrayDevirtualizer(Fn fn, const IndexMask *mask, const typename ParamType<Args>::type *...params)
       : fn_(std::move(fn)), mask_(*mask), params_{params...}
@@ -54,12 +57,57 @@ template<typename Fn, typename... Args> class ArrayDevirtualizer {
     this->init(std::make_index_sequence<sizeof...(Args)>{});
   }
 
-  void execute_fallback()
+  bool execute_fallback()
   {
+    BLI_assert(!executed_);
     this->execute_fallback_impl(std::make_index_sequence<sizeof...(Args)>{});
+    return true;
+  }
+
+  bool try_execute_devirtualized()
+  {
+    BLI_assert(!executed_);
+    return this->try_execute_devirtualized_impl();
   }
 
  private:
+  template<typename... Mode> bool try_execute_devirtualized_impl()
+  {
+    if constexpr (sizeof...(Mode) == sizeof...(Args)) {
+      this->try_execute_devirtualized_impl_call(std::tuple<Mode...>(),
+                                                std::make_index_sequence<sizeof...(Args)>());
+      return true;
+    }
+    else {
+      constexpr size_t I = sizeof...(Mode);
+      using ParamTag = std::tuple_element_t<I, TagsTuple>;
+      if constexpr (std::is_base_of_v<SingleInputTagBase, ParamTag>) {
+        if (varray_is_single_[I]) {
+          return this->try_execute_devirtualized_impl<Mode..., DevirtualizeSingle>();
+        }
+        else if (varray_is_span_[I]) {
+          return this->try_execute_devirtualized_impl<Mode..., DevirtualizeSpan>();
+        }
+        else {
+          return false;
+        }
+      }
+      else {
+        return this->try_execute_devirtualized_impl<Mode..., DevirtualizeNone>();
+      }
+    }
+  }
+
+  template<typename... Mode, size_t... I>
+  void try_execute_devirtualized_impl_call(std::tuple<Mode...> /* modes */,
+                                           std::index_sequence<I...> /* indices */)
+  {
+    fn_(mask_,
+        mask_,
+        this->get_execute_param<I, std::tuple_element_t<I, std::tuple<Mode...>>>()...);
+    executed_ = true;
+  }
+
   template<size_t... I> void init(std::index_sequence<I...> /* indices */)
   {
     varray_is_span_.fill(false);
@@ -79,24 +127,23 @@ template<typename Fn, typename... Args> class ArrayDevirtualizer {
 
   template<size_t... I> void execute_fallback_impl(std::index_sequence<I...> /* indices */)
   {
-    fn_(mask_, mask_, this->get_execute_param<I, DevirtualizeMode::None>()...);
+    fn_(mask_, mask_, this->get_execute_param<I, DevirtualizeNone>()...);
+    executed_ = true;
   }
 
-  template<size_t I, DevirtualizeMode mode> auto get_execute_param()
+  template<size_t I, typename Mode> auto get_execute_param()
   {
     using ParamTag = std::tuple_element_t<I, TagsTuple>;
     if constexpr (std::is_base_of_v<SingleInputTagBase, ParamTag>) {
       using T = typename ParamTag::BaseType;
-      static_assert(
-          ELEM(mode, DevirtualizeMode::None, DevirtualizeMode::Single, DevirtualizeMode::Span));
       const VArray<T> *varray = std::get<I>(params_);
-      if constexpr (mode == DevirtualizeMode::None) {
+      if constexpr (std::is_same_v<Mode, DevirtualizeNone>) {
         return *varray;
       }
-      else if constexpr (mode == DevirtualizeMode::Single) {
+      else if constexpr (std::is_same_v<Mode, DevirtualizeSingle>) {
         return SingleAsSpan(*varray);
       }
-      else if constexpr (mode == DevirtualizeMode::Span) {
+      else if constexpr (std::is_same_v<Mode, DevirtualizeSpan>) {
         return varray->get_internal_span();
       }
     }
diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
index b5851d5c5b3..91df8b06540 100644
--- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc
+++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
@@ -223,19 +223,31 @@ TEST(virtual_array, MaterializeCompressed)
   }
 }
 
-TEST(virtual_array, Devirtualize)
-{
-  auto fn = [](auto in_indices, auto out_indices, auto in1, auto in2, int *__restrict out1) {
+struct MyOperator {
+  template<typename InIndices, typename OutIndices, typename In1Array, typename In2Array>
+  void operator()(InIndices in_indices,
+                  OutIndices out_indices,
+                  In1Array in1,
+                  In2Array in2,
+                  int *__restrict out1)
+  {
     for (const int64_t i : IndexRange(in_indices.size())) {
       const int64_t in_i = in_indices[i];
       const int64_t out_i = out_indices[i];
       out1[out_i] = in1[in_i] + in2[in_i];
     }
-  };
+  }
+};
+
+TEST(virtual_array, Devirtualize)
+{
+  MyOperator fn;
 
   IndexMask mask(IndexRange(10));
   VArray<int> in1 = VArray<int>::ForSingle(3, 10);
-  VArray<int> in2 = VArray<int>::ForSingle(5, 10);
+  // VArray<int> in2 = VArray<int>::ForSingle(5, 10);
+  VArray<int> in2 = VArray<int>::ForContainer(Array<int>(10, 5));
+  // VArray<int> in2 = VArray<int>::ForFunc(10, [](int64_t i) { return (int)i; });
   std::array<int, 10> out1_array;
   MutableSpan<int> out1 = out1_array;
   out1.fill(-1);
@@ -243,7 +255,7 @@ TEST(virtual_array, Devirtualize)
   ArrayDevirtualizer<decltype(fn), SingleInputTag<int>, SingleInputTag<int>, SingleOutputTag<int>>
       devirtualizer{fn, &mask, &in1, &in2, &out1};
 
-  devirtualizer.execute_fallback();
+  devirtualizer.try_execute_devirtualized();
 
   EXPECT_EQ(out1[0], 8);
   EXPECT_EQ(out1[1], 8);



More information about the Bf-blender-cvs mailing list