[Bf-blender-cvs] [bf8a98ffc5a] functions: experimental lazy fgraph evaluation
Jacques Lucke
noreply at git.blender.org
Mon Mar 25 09:57:58 CET 2019
Commit: bf8a98ffc5a0a0d7a7059d14af1fc257fa53cc2b
Author: Jacques Lucke
Date: Mon Mar 25 09:57:44 2019 +0100
Branches: functions
https://developer.blender.org/rBbf8a98ffc5a0a0d7a7059d14af1fc257fa53cc2b
experimental lazy fgraph evaluation
===================================================================
M source/blender/blenlib/BLI_small_vector.hpp
M source/blender/functions/backends/tuple_call/fgraph_tuple_call.cpp
M source/blender/functions/backends/tuple_call/tuple.hpp
M source/blender/functions/backends/tuple_call/tuple_call.hpp
===================================================================
diff --git a/source/blender/blenlib/BLI_small_vector.hpp b/source/blender/blenlib/BLI_small_vector.hpp
index 182164b428b..8e86cb53861 100644
--- a/source/blender/blenlib/BLI_small_vector.hpp
+++ b/source/blender/blenlib/BLI_small_vector.hpp
@@ -85,6 +85,12 @@ namespace BLI {
this->grow(size);
}
+ void clear()
+ {
+ this->destruct_elements_but_keep_memory();
+ this->m_size = 0;
+ }
+
void append(const T &value)
{
this->ensure_space_for_one();
diff --git a/source/blender/functions/backends/tuple_call/fgraph_tuple_call.cpp b/source/blender/functions/backends/tuple_call/fgraph_tuple_call.cpp
index 476ae8f2230..b4174be2637 100644
--- a/source/blender/functions/backends/tuple_call/fgraph_tuple_call.cpp
+++ b/source/blender/functions/backends/tuple_call/fgraph_tuple_call.cpp
@@ -400,12 +400,167 @@ namespace FN {
}
};
+ class LazyExecFGraph : public TupleCallBody {
+ private:
+ FunctionGraph m_fgraph;
+
+ public:
+ LazyExecFGraph(FunctionGraph &fgraph)
+ : m_fgraph(fgraph)
+ {
+ auto *context = new llvm::LLVMContext();
+
+ for (Node *node : fgraph.graph()->all_nodes()) {
+ if (node->function()->has_body<TupleCallBody>()) {
+ continue;
+ }
+ if (node->function()->has_body<LazyInTupleCallBody>()) {
+ continue;
+ }
+ if (node->function()->has_body<LLVMBuildIRBody>()) {
+ derive_TupleCallBody_from_LLVMBuildIRBody(node->function(), *context);
+ }
+ }
+ }
+
+ void call(Tuple &fn_in, Tuple &fn_out) const override
+ {
+ SocketSet required_sockets = m_fgraph.find_required_sockets();
+ for (Socket socket : m_fgraph.inputs()) {
+ required_sockets.add(socket);
+ }
+
+ SmallVector<SharedType> temp_storage_types;
+ SmallMap<Socket, uint> socket_indices;
+
+ uint index = 0;
+ for (Socket socket : required_sockets) {
+ temp_storage_types.append(socket.type());
+ socket_indices.add(socket, index);
+ index++;
+ }
+
+ auto temp_meta = SharedTupleMeta::New(temp_storage_types);
+ Tuple temp_storage(temp_meta);
+
+ for (uint i = 0; i < m_fgraph.inputs().size(); i++) {
+ Socket socket = m_fgraph.inputs()[i];
+ Tuple::relocate_element(
+ fn_in, i,
+ temp_storage, socket_indices.lookup(socket));
+ }
+
+ for (uint i = 0; i < m_fgraph.outputs().size(); i++) {
+ Socket socket = m_fgraph.outputs()[i];
+ this->compute_socket(socket, temp_storage, socket_indices);
+ }
+
+ for (uint i = 0; i < m_fgraph.outputs().size(); i++) {
+ Socket socket = m_fgraph.outputs()[i];
+ Tuple::relocate_element(
+ temp_storage, socket_indices.lookup(socket),
+ fn_out, i);
+ }
+ }
+
+ void compute_socket(
+ Socket socket,
+ Tuple &temp_storage,
+ const SmallMap<Socket, uint> &socket_indices) const
+ {
+ uint socket_index = socket_indices.lookup(socket);
+ if (temp_storage.is_initialized(socket_index)) {
+ /* do nothing */
+ }
+ else if (socket.is_input()) {
+ Socket origin_socket = socket.origin();
+ this->compute_socket(origin_socket, temp_storage, socket_indices);
+ Tuple::copy_element(
+ temp_storage, socket_indices.lookup(origin_socket),
+ temp_storage, socket_indices.lookup(socket));
+ }
+ else if (socket.is_output()) {
+ Node *node = socket.node();
+ SharedFunction &fn = node->function();
+
+ if (fn->has_body<LazyInTupleCallBody>()) {
+ auto *body = node->function()->body<LazyInTupleCallBody>();
+
+ FN_TUPLE_STACK_ALLOC(fn_in, body->meta_in());
+ FN_TUPLE_STACK_ALLOC(fn_out, body->meta_out());
+
+ for (uint input_index : body->always_required()) {
+ Socket input_socket = node->input(input_index);
+ this->compute_socket(
+ input_socket, temp_storage, socket_indices);
+ Tuple::copy_element(
+ temp_storage, socket_indices.lookup(input_socket),
+ fn_in, input_index);
+ }
+
+ void *user_data = alloca(body->user_data_size());
+ LazyState lazy_state(user_data);
+
+ while (!lazy_state.is_done()) {
+ lazy_state.start_next_entry();
+ body->call(fn_in, fn_out, lazy_state);
+ for (uint input_index : lazy_state.requested_inputs()) {
+ Socket input_socket = node->input(input_index);
+ this->compute_socket(
+ input_socket, temp_storage, socket_indices);
+ Tuple::copy_element(
+ temp_storage, socket_indices.lookup(input_socket),
+ fn_in, input_index);
+ }
+ }
+ BLI_assert(fn_out.all_initialized());
+
+ for (uint output_index = 0; output_index < node->output_amount(); output_index++) {
+ Socket output_socket = node->output(output_index);
+ Tuple::relocate_element(
+ fn_out, output_index,
+ temp_storage, socket_indices.lookup(output_socket));
+ }
+ }
+ else if (fn->has_body<TupleCallBody>()) {
+ auto *body = node->function()->body<TupleCallBody>();
+
+ FN_TUPLE_STACK_ALLOC(fn_in, body->meta_in());
+ FN_TUPLE_STACK_ALLOC(fn_out, body->meta_out());
+
+ for (uint input_index = 0; input_index < node->input_amount(); input_index++) {
+ Socket input_socket = node->input(input_index);
+ this->compute_socket(
+ input_socket, temp_storage, socket_indices);
+ Tuple::copy_element(
+ temp_storage, socket_indices.lookup(input_socket),
+ fn_in, input_index);
+ }
+
+ body->call(fn_in, fn_out);
+ BLI_assert(fn_out.all_initialized());
+
+ for (uint output_index = 0; output_index < node->output_amount(); output_index++) {
+ Socket output_socket = node->output(output_index);
+ Tuple::relocate_element(
+ fn_out, output_index,
+ temp_storage, socket_indices.lookup(output_socket));
+ }
+ }
+ else {
+ BLI_assert(false);
+ }
+ }
+ }
+ };
+
void fgraph_add_TupleCallBody(
SharedFunction &fn,
FunctionGraph &fgraph)
{
// fn->add_body(new ExecuteGraph(fgraph));
- fn->add_body(new InterpretFGraph(fgraph));
+ // fn->add_body(new InterpretFGraph(fgraph));
+ fn->add_body(new LazyExecFGraph(fgraph));
}
} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/backends/tuple_call/tuple.hpp b/source/blender/functions/backends/tuple_call/tuple.hpp
index 356d405de45..506d517a17a 100644
--- a/source/blender/functions/backends/tuple_call/tuple.hpp
+++ b/source/blender/functions/backends/tuple_call/tuple.hpp
@@ -236,6 +236,12 @@ namespace FN {
return this->element_ref<T>(index);
}
+ inline bool is_initialized(uint index) const
+ {
+ BLI_assert(index < m_meta->element_amount());
+ return m_initialized[index];
+ }
+
static inline void copy_element(
const Tuple &from, uint from_index,
Tuple &to, uint to_index)
@@ -256,6 +262,28 @@ namespace FN {
}
}
+ static inline void relocate_element(
+ Tuple &from, uint from_index,
+ Tuple &to, uint to_index)
+ {
+ BLI_assert(from.m_initialized[from_index]);
+ BLI_assert(from.m_meta->types()[from_index] == to.m_meta->types()[to_index]);
+
+ void *src = from.element_ptr(from_index);
+ void *dst = to.element_ptr(to_index);
+ CPPTypeInfo *type_info = from.m_meta->type_infos()[from_index];
+
+ if (to.m_initialized[to_index]) {
+ type_info->relocate_to_initialized(src, dst);
+ }
+ else {
+ type_info->relocate_to_uninitialized(src, dst);
+ to.m_initialized[to_index] = true;
+ }
+
+ from.m_initialized[from_index] = false;
+ }
+
inline void init_default(uint index) const
{
CPPTypeInfo *type_info = m_meta->type_infos()[index];
diff --git a/source/blender/functions/backends/tuple_call/tuple_call.hpp b/source/blender/functions/backends/tuple_call/tuple_call.hpp
index adab1a12efd..295d9406723 100644
--- a/source/blender/functions/backends/tuple_call/tuple_call.hpp
+++ b/source/blender/functions/backends/tuple_call/tuple_call.hpp
@@ -49,6 +49,7 @@ namespace FN {
void start_next_entry()
{
m_entry_count++;
+ m_requested_inputs.clear();
}
void request_input(uint index)
@@ -61,6 +62,11 @@ namespace FN {
m_is_done = true;
}
+ const SmallVector<uint> &requested_inputs() const
+ {
+ return m_requested_inputs;
+ }
+
bool is_first_entry() const
{
return m_entry_count == 1;
More information about the Bf-blender-cvs
mailing list