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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to