[Bf-blender-cvs] [e7c95b8fdef] temp-geometry-nodes-evaluator-refactor: cleanup + add initial side effect provider
Jacques Lucke
noreply at git.blender.org
Tue Sep 6 20:09:56 CEST 2022
Commit: e7c95b8fdef2a657b5b1503cab21fccdb7c641ff
Author: Jacques Lucke
Date: Tue Sep 6 18:12:59 2022 +0200
Branches: temp-geometry-nodes-evaluator-refactor
https://developer.blender.org/rBe7c95b8fdef2a657b5b1503cab21fccdb7c641ff
cleanup + add initial side effect provider
===================================================================
M source/blender/functions/FN_lazy_function_graph_executor.hh
M source/blender/functions/intern/lazy_function_graph_executor.cc
M source/blender/functions/tests/FN_lazy_function_test.cc
M source/blender/modifiers/intern/MOD_nodes.cc
M source/blender/nodes/intern/geometry_nodes_to_lazy_function_graph.cc
===================================================================
diff --git a/source/blender/functions/FN_lazy_function_graph_executor.hh b/source/blender/functions/FN_lazy_function_graph_executor.hh
index 14470936804..86a7592e982 100644
--- a/source/blender/functions/FN_lazy_function_graph_executor.hh
+++ b/source/blender/functions/FN_lazy_function_graph_executor.hh
@@ -6,6 +6,7 @@
* \ingroup fn
*/
+#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "FN_lazy_function_graph.hh"
@@ -19,21 +20,44 @@ class LazyFunctionGraphExecutionLogger {
GPointer value) const;
};
+class LazyFunctionGraphExecutionSideEffectProvider {
+ public:
+ virtual Vector<const Node *> get_nodes_with_side_effects(const Context &context) const;
+};
+
class LazyFunctionGraphExecutor : public LazyFunction {
public:
using Logger = LazyFunctionGraphExecutionLogger;
+ using SideEffectProvider = LazyFunctionGraphExecutionSideEffectProvider;
private:
+ /**
+ * The graph that is evaluated.
+ */
const LazyFunctionGraph &graph_;
+ /**
+ * Input and output sockets of the entire graph.
+ */
VectorSet<const OutputSocket *> graph_inputs_;
VectorSet<const InputSocket *> graph_outputs_;
+ /**
+ * Optional logger for events that happen during execution.
+ */
const Logger *logger_;
+ /**
+ * Optional side effect provider. It knows which nodes have side effects based on the context
+ * during evaluation.
+ */
+ const SideEffectProvider *side_effect_provider_;
+
+ friend class Executor;
public:
LazyFunctionGraphExecutor(const LazyFunctionGraph &graph,
Span<const OutputSocket *> graph_inputs,
Span<const InputSocket *> graph_outputs,
- const Logger *logger);
+ const Logger *logger,
+ const SideEffectProvider *side_effect_provider);
void *init_storage(LinearAllocator<> &allocator) const override;
void destruct_storage(void *storage) const override;
diff --git a/source/blender/functions/intern/lazy_function_graph_executor.cc b/source/blender/functions/intern/lazy_function_graph_executor.cc
index 788f14f3b03..7c5c908aa94 100644
--- a/source/blender/functions/intern/lazy_function_graph_executor.cc
+++ b/source/blender/functions/intern/lazy_function_graph_executor.cc
@@ -169,19 +169,13 @@ class GraphExecutorLFParams;
class Executor {
private:
+ const LazyFunctionGraphExecutor &self_;
/**
- * The graph that is evaluated.
+ * Usually nodes are only executed when at least one of their outputs are required.
+ * Sometimes we want to execute nodes for their side effects though. So this is a list of all the
+ * nodes that should be executed even when their outputs are not required.
*/
- const LazyFunctionGraph &graph_;
- /**
- * Input and output sockets of the entire graph.
- */
- const VectorSet<const OutputSocket *> &graph_inputs_;
- const VectorSet<const InputSocket *> &graph_outputs_;
- /**
- * Optional logger for events that happen during execution.
- */
- const LazyFunctionGraphExecutor::Logger *logger_;
+ const Vector<const Node *> side_effect_nodes_;
/**
* Remembers which inputs have been loaded from the caller already, to avoid loading them twice.
* Atomics are used to make sure that every input is only retrieved once.
@@ -213,18 +207,11 @@ class Executor {
friend GraphExecutorLFParams;
public:
- Executor(const LazyFunctionGraph &graph,
- const VectorSet<const OutputSocket *> &graph_inputs,
- const VectorSet<const InputSocket *> &graph_outputs,
- const LazyFunctionGraphExecutor::Logger *logger)
- : graph_(graph),
- graph_inputs_(graph_inputs),
- graph_outputs_(graph_outputs),
- logger_(logger),
- loaded_inputs_(graph_inputs.size())
+ Executor(const LazyFunctionGraphExecutor &self)
+ : self_(self), loaded_inputs_(self.graph_inputs_.size())
{
/* The indices are necessary, because they are used as keys in #node_states_. */
- BLI_assert(graph_.node_indices_are_valid());
+ BLI_assert(self_.graph_.node_indices_are_valid());
this->initialize_node_states();
task_pool_ = BLI_task_pool_create(this, TASK_PRIORITY_HIGH);
@@ -237,7 +224,7 @@ class Executor {
BLI_task_pool_free(task_pool_);
threading::parallel_for(node_states_.index_range(), 1024, [&](const IndexRange range) {
for (const int node_index : range) {
- const Node &node = *graph_.nodes()[node_index];
+ const Node &node = *self_.graph_.nodes()[node_index];
NodeState &node_state = *node_states_[node_index];
this->destruct_node_state(node, node_state);
}
@@ -288,7 +275,7 @@ class Executor {
private:
void initialize_node_states()
{
- Span<const Node *> nodes = graph_.nodes();
+ Span<const Node *> nodes = self_.graph_.nodes();
node_states_.reinitialize(nodes.size());
/* Construct all node states in parallel. */
@@ -341,14 +328,14 @@ class Executor {
void schedule_newly_requested_outputs(CurrentTask ¤t_task)
{
- for (const int graph_output_index : graph_outputs_.index_range()) {
+ for (const int graph_output_index : self_.graph_outputs_.index_range()) {
if (params_->get_output_usage(graph_output_index) != ValueUsage::Used) {
continue;
}
if (params_->output_was_set(graph_output_index)) {
continue;
}
- const InputSocket &socket = *graph_outputs_[graph_output_index];
+ const InputSocket &socket = *self_.graph_outputs_[graph_output_index];
const Node &node = socket.node();
NodeState &node_state = *node_states_[node.index_in_graph()];
this->with_locked_node(node, node_state, current_task, [&](LockedNode &locked_node) {
@@ -359,8 +346,8 @@ class Executor {
void set_defaulted_graph_outputs()
{
- for (const int graph_output_index : graph_outputs_.index_range()) {
- const InputSocket &socket = *graph_outputs_[graph_output_index];
+ for (const int graph_output_index : self_.graph_outputs_.index_range()) {
+ const InputSocket &socket = *self_.graph_outputs_[graph_output_index];
if (socket.origin() != nullptr) {
continue;
}
@@ -368,8 +355,8 @@ class Executor {
const void *default_value = socket.default_value();
BLI_assert(default_value != nullptr);
- if (logger_ != nullptr) {
- logger_->log_socket_value(*context_, socket, {type, default_value});
+ if (self_.logger_ != nullptr) {
+ self_.logger_->log_socket_value(*context_, socket, {type, default_value});
}
void *output_ptr = params_->get_output_data_ptr(graph_output_index);
@@ -380,8 +367,8 @@ class Executor {
void set_always_unused_graph_inputs()
{
- for (const int i : graph_inputs_.index_range()) {
- const OutputSocket &socket = *graph_inputs_[i];
+ for (const int i : self_.graph_inputs_.index_range()) {
+ const OutputSocket &socket = *self_.graph_inputs_[i];
const Node &node = socket.node();
const NodeState &node_state = *node_states_[node.index_in_graph()];
const OutputState &output_state = node_state.outputs[socket.index_in_node()];
@@ -394,7 +381,7 @@ class Executor {
void forward_newly_provided_inputs(CurrentTask ¤t_task)
{
LinearAllocator<> &allocator = local_allocators_.local();
- for (const int graph_input_index : graph_inputs_.index_range()) {
+ for (const int graph_input_index : self_.graph_inputs_.index_range()) {
std::atomic<bool> &was_loaded = loaded_inputs_[graph_input_index];
if (was_loaded.load(std::memory_order_relaxed)) {
continue;
@@ -416,7 +403,7 @@ class Executor {
const int graph_input_index,
void *input_data)
{
- const OutputSocket &socket = *graph_inputs_[graph_input_index];
+ const OutputSocket &socket = *self_.graph_inputs_[graph_input_index];
const CPPType &type = socket.type();
void *buffer = allocator.allocate(type.size(), type.alignment());
type.move_construct(input_data, buffer);
@@ -431,7 +418,7 @@ class Executor {
OutputState &output_state = node_state.outputs[index_in_node];
if (node.is_dummy()) {
- const int graph_input_index = graph_inputs_.index_of(&socket);
+ const int graph_input_index = self_.graph_inputs_.index_of(&socket);
std::atomic<bool> &was_loaded = loaded_inputs_[graph_input_index];
if (was_loaded.load(std::memory_order_relaxed)) {
return;
@@ -473,7 +460,7 @@ class Executor {
if (output_state.usage == ValueUsage::Maybe) {
output_state.usage = ValueUsage::Unused;
if (node.is_dummy()) {
- const int graph_input_index = graph_inputs_.index_of(&socket);
+ const int graph_input_index = self_.graph_inputs_.index_of(&socket);
params_->set_input_unused(graph_input_index);
}
else {
@@ -615,8 +602,8 @@ class Executor {
const CPPType &type = input_socket.type();
const void *default_value = input_socket.default_value();
BLI_assert(default_value != nullptr);
- if (logger_ != nullptr) {
- logger_->log_socket_value(*context_, input_socket, {type, default_value});
+ if (self_.logger_ != nullptr) {
+ self_.logger_->log_socket_value(*context_, input_socket, {type, default_value});
}
void *buffer = allocator.allocate(type.size(), type.alignment());
type.copy_construct(default_value, buffer);
@@ -820,8 +807,8 @@ class Executor {
LinearAllocator<> &allocator = local_allocators_.local();
const CPPType &type = *value_to_forward.type();
- if (logger_ != nullptr) {
- logger_->log_socket_value(*context_, from_socket, value_to_forward);
+ if (self_.logger_ != nullptr) {
+ self_.logger_->log_socket_value(*context_, from_socket, value_to_forward);
}
const Span<const InputSocket *> targets = from_socket.targets();
@@ -836,11 +823,11 @@ class Executor {
BLI_assert(target_socket->type() == type);
BLI_assert(target_
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list