diff options
author | Jacques Lucke <jacques@blender.org> | 2022-04-10 16:17:57 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2022-04-10 16:17:57 +0300 |
commit | f7908bda064209fb9010a5d3622aa62b5b9f20ed (patch) | |
tree | 4f2f419c028a96f41ea4fc30402381ff85ba5754 | |
parent | 3e5b98827272aed2f9efce9c98348d3a49901541 (diff) |
support execute materialized
-rw-r--r-- | source/blender/blenlib/BLI_virtual_array_devirtualize.hh | 59 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_virtual_array_test.cc | 2 |
2 files changed, 60 insertions, 1 deletions
diff --git a/source/blender/blenlib/BLI_virtual_array_devirtualize.hh b/source/blender/blenlib/BLI_virtual_array_devirtualize.hh index 3164dcf459b..2293b55b663 100644 --- a/source/blender/blenlib/BLI_virtual_array_devirtualize.hh +++ b/source/blender/blenlib/BLI_virtual_array_devirtualize.hh @@ -37,6 +37,9 @@ struct DevirtualizeSpan { struct DevirtualizeSingle { }; +template<typename TagsTuple, size_t I> +using BaseType = typename std::tuple_element_t<I, TagsTuple>::BaseType; + template<typename Fn, typename... Args> class ArrayDevirtualizer { private: using TagsTuple = std::tuple<Args...>; @@ -69,7 +72,63 @@ template<typename Fn, typename... Args> class ArrayDevirtualizer { return this->try_execute_devirtualized_impl(); } + void execute_materialized() + { + BLI_assert(!executed_); + this->execute_materialized_impl(std::make_index_sequence<sizeof...(Args)>{}); + } + private: + template<size_t... I> void execute_materialized_impl(std::index_sequence<I...> /* indices */) + { + static constexpr int64_t MaxChunkSize = 32; + const int64_t mask_size = mask_.size(); + std::tuple<TypedBuffer<BaseType<TagsTuple, I>, MaxChunkSize>...> buffers_owner; + std::tuple<MutableSpan<BaseType<TagsTuple, I>>...> buffers = { + MutableSpan{std::get<I>(buffers_owner).ptr(), std::min(mask_size, MaxChunkSize)}...}; + + 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); + const int64_t sliced_mask_size = sliced_mask.size(); + ( + [&]() { + using ParamTag = std::tuple_element_t<I, TagsTuple>; + using T = typename ParamTag::BaseType; + if constexpr (std::is_base_of_v<SingleInputTagBase, ParamTag>) { + MutableSpan in_chunk = std::get<I>(buffers).take_front(sliced_mask_size); + const VArray<T> *varray = std::get<I>(params_); + varray->materialize_compressed_to_uninitialized(sliced_mask, in_chunk); + } + }(), + ...); + + fn_(IndexRange(sliced_mask_size), sliced_mask, [&]() { + using ParamTag = std::tuple_element_t<I, TagsTuple>; + using T = typename ParamTag::BaseType; + if constexpr (std::is_base_of_v<SingleInputTagBase, ParamTag>) { + MutableSpan<T> in_chunk = std::get<I>(buffers).take_front(sliced_mask_size); + return in_chunk; + } + else if constexpr (std::is_base_of_v<SingleOutputTagBase, ParamTag>) { + MutableSpan<T> out_span = *std::get<I>(params_); + return out_span.data(); + } + }()...); + + ( + [&]() { + using ParamTag = std::tuple_element_t<I, TagsTuple>; + using T = typename ParamTag::BaseType; + if constexpr (std::is_base_of_v<SingleInputTagBase, ParamTag>) { + MutableSpan<T> in_chunk = std::get<I>(buffers); + destruct_n(in_chunk.data(), sliced_mask_size); + } + }(), + ...); + } + } + template<typename... Mode> bool try_execute_devirtualized_impl() { if constexpr (sizeof...(Mode) == sizeof...(Args)) { diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc index 95222e72bb0..a1d43c89cdf 100644 --- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc +++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc @@ -256,7 +256,7 @@ TEST(virtual_array, Devirtualize) devirtualizer{fn, &mask, &in1, &in2, &out1}; if (!devirtualizer.try_execute_devirtualized()) { - devirtualizer.execute_fallback(); + devirtualizer.execute_materialized(); } EXPECT_EQ(out1[0], 8); |