[Bf-blender-cvs] [5296f03f9ff] functions: initial generic automatic vectorization, used in Combine Vector node
Jacques Lucke
noreply at git.blender.org
Sat Apr 6 18:47:20 CEST 2019
Commit: 5296f03f9ffefc6e64d13462729a9b00a6ce389f
Author: Jacques Lucke
Date: Sat Apr 6 17:21:07 2019 +0200
Branches: functions
https://developer.blender.org/rB5296f03f9ffefc6e64d13462729a9b00a6ce389f
initial generic automatic vectorization, used in Combine Vector node
===================================================================
M source/blender/blenlib/BLI_small_vector.hpp
M source/blender/functions/CMakeLists.txt
M source/blender/functions/FN_functions.hpp
M source/blender/functions/backends/tuple_call/tuple_call.hpp
M source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
A source/blender/functions/functions/auto_vectorization.cpp
A source/blender/functions/functions/auto_vectorization.hpp
M source/blender/functions/functions/vectors.cpp
===================================================================
diff --git a/source/blender/blenlib/BLI_small_vector.hpp b/source/blender/blenlib/BLI_small_vector.hpp
index 025534351d2..c5ffee5dc7a 100644
--- a/source/blender/blenlib/BLI_small_vector.hpp
+++ b/source/blender/blenlib/BLI_small_vector.hpp
@@ -172,6 +172,11 @@ namespace BLI {
return -1;
}
+ bool contains(const T &value) const
+ {
+ return this->index(value) != -1;
+ }
+
static bool all_equal(const SmallVector &a, const SmallVector &b)
{
if (a.size() != b.size()) {
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index d0313d51a7a..098d571e6a0 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -116,6 +116,8 @@ set(SRC
functions/simple_conversions.cpp
functions/switch.hpp
functions/switch.cpp
+ functions/auto_vectorization.hpp
+ functions/auto_vectorization.cpp
frontends/data_flow_nodes/builder.hpp
frontends/data_flow_nodes/builder.cpp
diff --git a/source/blender/functions/FN_functions.hpp b/source/blender/functions/FN_functions.hpp
index 4da5b8b27e0..d1090a80f44 100644
--- a/source/blender/functions/FN_functions.hpp
+++ b/source/blender/functions/FN_functions.hpp
@@ -6,4 +6,5 @@
#include "functions/vectors.hpp"
#include "functions/lists.hpp"
#include "functions/simple_conversions.hpp"
-#include "functions/switch.hpp"
\ No newline at end of file
+#include "functions/switch.hpp"
+#include "functions/auto_vectorization.hpp"
\ No newline at end of file
diff --git a/source/blender/functions/backends/tuple_call/tuple_call.hpp b/source/blender/functions/backends/tuple_call/tuple_call.hpp
index 93a01b3bd9d..6f124b0da4a 100644
--- a/source/blender/functions/backends/tuple_call/tuple_call.hpp
+++ b/source/blender/functions/backends/tuple_call/tuple_call.hpp
@@ -33,6 +33,14 @@ namespace FN {
public:
BLI_COMPOSITION_DECLARATION(TupleCallBody);
+ inline void call__setup_stack(Tuple &fn_in, Tuple &fn_out, ExecutionContext &ctx)
+ {
+ TextStackFrame frame(this->owner()->name().c_str());
+ ctx.stack().push(&frame);
+ this->call(fn_in, fn_out, ctx);
+ ctx.stack().pop();
+ }
+
virtual void call(Tuple &fn_in, Tuple &fn_out, ExecutionContext &ctx) const = 0;
};
diff --git a/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp b/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
index 1ccdcbec38b..f0b9b6d6f1f 100644
--- a/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
+++ b/source/blender/functions/frontends/data_flow_nodes/inserters/nodes.cpp
@@ -211,14 +211,57 @@ namespace FN { namespace DataFlowNodes {
builder.map_sockets(ctx, node, bnode);
}
+ static bool vectorized_socket_is_list(PointerRNA *ptr, const char *prop_name)
+ {
+ BLI_assert(RNA_string_length(ptr, prop_name) == strlen("BASE"));
+ char value[5];
+ RNA_string_get(ptr, prop_name, value);
+ BLI_assert(STREQ(value, "BASE") || STREQ(value, "LIST"));
+ return STREQ(value, "LIST");
+ }
+
+ static SharedFunction original_or_vectorized(
+ SharedFunction &fn, const SmallVector<bool> vectorized_inputs)
+ {
+ if (vectorized_inputs.contains(true)) {
+ return Functions::auto_vectorization(fn, vectorized_inputs);
+ }
+ else {
+ return fn;
+ }
+ }
+
+ static void insert_combine_vector_node(
+ Builder &builder,
+ const BuilderContext &ctx,
+ bNode *bnode)
+ {
+ PointerRNA ptr;
+ ctx.get_rna(bnode, &ptr);
+
+ SmallVector<bool> vectorized_inputs = {
+ vectorized_socket_is_list(&ptr, "use_list__x"),
+ vectorized_socket_is_list(&ptr, "use_list__y"),
+ vectorized_socket_is_list(&ptr, "use_list__z"),
+ };
+
+ SharedFunction &original_fn = Functions::combine_vector();
+ SharedFunction final_fn = original_or_vectorized(
+ original_fn, vectorized_inputs);
+
+ Node *node = builder.insert_function(final_fn, ctx.btree(), bnode);
+ builder.map_sockets(ctx, node, bnode);
+ }
+
void register_node_inserters(GraphInserters &inserters)
{
- inserters.reg_node_function("fn_CombineVectorNode", Functions::combine_vector);
inserters.reg_node_function("fn_SeparateVectorNode", Functions::separate_vector);
inserters.reg_node_function("fn_VectorDistanceNode", Functions::separate_vector);
inserters.reg_node_function("fn_RandomNumberNode", Functions::random_number);
inserters.reg_node_function("fn_MapRangeNode", Functions::map_range);
+ //inserters.reg_node_function("fn_CombineVectorNode", Functions::combine_vector);
+ inserters.reg_node_inserter("fn_CombineVectorNode", insert_combine_vector_node);
inserters.reg_node_inserter("fn_ObjectTransformsNode", insert_object_transforms_node);
inserters.reg_node_inserter("fn_FloatMathNode", insert_float_math_node);
inserters.reg_node_inserter("fn_VectorMathNode", insert_vector_math_node);
diff --git a/source/blender/functions/functions/auto_vectorization.cpp b/source/blender/functions/functions/auto_vectorization.cpp
new file mode 100644
index 00000000000..31cb2501d8c
--- /dev/null
+++ b/source/blender/functions/functions/auto_vectorization.cpp
@@ -0,0 +1,233 @@
+#include <cmath>
+
+#include "FN_functions.hpp"
+#include "FN_types.hpp"
+#include "FN_tuple_call.hpp"
+
+namespace FN { namespace Functions {
+
+ class AutoVectorization : public TupleCallBody {
+ private:
+ SharedFunction m_main;
+ TupleCallBody *m_main_body;
+
+ const SmallVector<bool> m_input_is_list;
+ SmallVector<uint> m_list_inputs;
+
+ SmallVector<TupleCallBody *> m_get_length_bodies;
+ uint m_max_len_in_size, m_max_len_out_size;
+
+ SmallVector<TupleCallBody *> m_get_element_bodies;
+ SmallVector<TupleCallBody *> m_create_empty_bodies;
+ SmallVector<TupleCallBody *> m_append_bodies;
+
+ public:
+ AutoVectorization(
+ SharedFunction main,
+ const SmallVector<bool> &input_is_list)
+ : m_main(main),
+ m_main_body(main->body<TupleCallBody>()),
+ m_input_is_list(input_is_list)
+ {
+ for (uint i = 0; i < input_is_list.size(); i++) {
+ if (input_is_list[i]) {
+ m_list_inputs.append(i);
+ }
+ }
+ for (uint i : m_list_inputs) {
+ SharedType &base_type = main->signature().inputs()[i].type();
+ m_get_length_bodies.append(list_length(base_type)->body<TupleCallBody>());
+ m_get_element_bodies.append(get_list_element(base_type)->body<TupleCallBody>());
+ }
+
+ m_max_len_in_size = 0;
+ m_max_len_out_size = 0;
+ for (TupleCallBody *body : m_get_length_bodies) {
+ m_max_len_in_size = std::max(m_max_len_in_size, body->meta_in()->total_size());
+ m_max_len_out_size = std::max(m_max_len_out_size, body->meta_out()->total_size());
+ }
+
+ for (auto output : main->signature().outputs()) {
+ SharedType &base_type = output.type();
+ m_create_empty_bodies.append(empty_list(base_type)->body<TupleCallBody>());
+ m_append_bodies.append(append_to_list(base_type)->body<TupleCallBody>());
+ }
+ }
+
+ void call(Tuple &fn_in, Tuple &fn_out, ExecutionContext &ctx) const override
+ {
+ uint *input_lengths = BLI_array_alloca(input_lengths, m_list_inputs.size());
+ this->get_input_list_lengths(fn_in, ctx, input_lengths);
+
+ uint max_length = 0;
+ for (uint i = 0; i < m_list_inputs.size(); i++) {
+ max_length = std::max(max_length, input_lengths[i]);
+ }
+
+ ctx.print_with_traceback("Final Length: " + std::to_string(max_length));
+
+ this->initialize_empty_lists(fn_out, ctx);
+
+ FN_TUPLE_STACK_ALLOC(main_in, m_main_body->meta_in());
+ FN_TUPLE_STACK_ALLOC(main_out, m_main_body->meta_out());
+
+ for (uint iteration = 0; iteration < max_length; iteration++) {
+ uint list_index = 0;
+ for (uint i = 0; i < m_input_is_list.size(); i++) {
+ if (m_input_is_list[i]) {
+ this->copy_in_iteration(iteration, fn_in, main_in, i, list_index, input_lengths[list_index], ctx);
+ list_index++;
+ }
+ else {
+ Tuple::copy_element(fn_in, i, main_in, i);
+ }
+ }
+
+ m_main_body->call(main_in, main_out, ctx);
+
+ for (uint i = 0; i < m_main->signature().outputs().size(); i++) {
+ this->append_to_output(main_out, fn_out, i, ctx);
+ }
+ }
+
+ FN_TUPLE_STACK_FREE(main_in);
+ FN_TUPLE_STACK_FREE(main_out);
+ }
+
+ private:
+ void get_input_list_lengths(Tuple &fn_in, ExecutionContext &ctx, uint *r_lengths) const
+ {
+ void *buf_in = alloca(m_max_len_in_size);
+ void *buf_out = alloca(m_max_len_out_size);
+
+ for (uint i = 0; i < m_list_inputs.size(); i++) {
+ uint index = m_list_inputs[i];
+ TupleCallBody *body = m_get_length_bodies[i];
+
+ Tuple &len_in = Tuple::NewInBuffer(body->meta_in(), buf_in);
+ Tuple &len_out = Tuple::NewInBuffer(body->meta_out(), buf_out);
+
+ Tuple::copy_element(fn_in, index, len_in, 0);
+
+ body->call__setup_stack(len_in, len_out, ctx);
+
+ uint length = len_out.get<uint>(0);
+ r_lengths[i] = length;
+
+ len_in.~Tuple();
+ len_out.~Tuple();
+ }
+ }
+
+ void copy_in_iteration(uint iteration, Tuple &fn_in, Tuple &main_in, uint index, uint list_index, uint list_length, ExecutionContext &ctx) const
+ {
+ if (list_length == 0) {
+ main_in.init_default(index);
+ return;
+ }
+
+ TupleCallBody *body = m_get_element_bodies[list_index];
+
+ uint load_index = iteration % list_length;
+ FN_TUPLE_STACK_ALLOC(get_element_in, body->meta_in());
+ FN_TUPLE_STACK_ALLOC(get_element_out, body->meta_out());
+
+ Tuple::copy_element(fn_in, index, get_element_in, 0);
+ get_element_in.set<uint>(1, load_index);
+ get_element_in.init_default(2);
+
+ body->call__setup_stack(get_element_in, get_element_out, ctx);
+
+ Tuple::relocate_element(get_element_out, 0, main_in, index);
+
+ FN_TUPLE_STACK_FREE(get_element_in);
+ FN_TUPLE_STACK_FREE(get_element_out);
+ }
+
+ void initialize_empty_lists(Tuple &fn_out, ExecutionContext &ctx) const
+ {
+ for (uint i = 0; i < m_main->signature().outputs().size(); i++) {
+ this->initialize_empty_list(fn_out, i, ctx);
+ }
+ }
+
+ void initialize_empty_list(Tuple &fn_out, uint index, ExecutionContext &ctx) const
+ {
+ TupleCallBody *body = m_create_empty_bodies[index];
+
+ FN_TUPLE_STACK_ALLOC(create_list_in, body->meta_in());
+ FN_TUPLE_STACK_ALLOC(create_list_out, body->meta_out());
+
+ body->call__setu
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list