tornavis/source/blender/functions/FN_lazy_function_graph_exec...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

142 lines
4.7 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
#pragma once
/** \file
* \ingroup fn
*
* This file provides means to create a #LazyFunction from #Graph (which could then e.g. be used in
* another #Graph again).
*/
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "FN_lazy_function_graph.hh"
namespace blender::fn::lazy_function {
/**
* Can be implemented to log values produced during graph evaluation.
*/
class GraphExecutorLogger {
public:
virtual ~GraphExecutorLogger() = default;
virtual void log_socket_value(const Socket &socket,
GPointer value,
const Context &context) const;
virtual void log_before_node_execute(const FunctionNode &node,
const Params &params,
const Context &context) const;
virtual void log_after_node_execute(const FunctionNode &node,
const Params &params,
const Context &context) const;
virtual void dump_when_outputs_are_missing(const FunctionNode &node,
Span<const OutputSocket *> missing_sockets,
const Context &context) const;
virtual void dump_when_input_is_set_twice(const InputSocket &target_socket,
const OutputSocket &from_socket,
const Context &context) const;
};
/**
* Has to be implemented when some of the nodes in the graph may have side effects. The
* #GraphExecutor has to know about that to make sure that these nodes will be executed even though
* their outputs are not needed.
*/
class GraphExecutorSideEffectProvider {
public:
virtual ~GraphExecutorSideEffectProvider() = default;
virtual Vector<const FunctionNode *> get_nodes_with_side_effects(const Context &context) const;
};
/**
* Can be used to pass extra context into the execution of a function. The main alternative to this
* is to create a wrapper `LazyFunction` for the `FunctionNode`s. Using this light weight wrapper
* is preferable if possible.
*/
class GraphExecutorNodeExecuteWrapper {
public:
virtual ~GraphExecutorNodeExecuteWrapper() = default;
/**
* Is expected to run `node.function().execute(params, context)` but might do some extra work,
* like adjusting the context.
*/
virtual void execute_node(const FunctionNode &node,
Params &params,
const Context &context) const = 0;
};
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
class GraphExecutor : public LazyFunction {
public:
using Logger = GraphExecutorLogger;
using SideEffectProvider = GraphExecutorSideEffectProvider;
using NodeExecuteWrapper = GraphExecutorNodeExecuteWrapper;
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
private:
/**
* The graph that is evaluated.
*/
const Graph &graph_;
/**
* Input and output sockets of the entire graph.
*/
Vector<const GraphInputSocket *> graph_inputs_;
Vector<const GraphOutputSocket *> graph_outputs_;
Array<int> graph_input_index_by_socket_index_;
Array<int> graph_output_index_by_socket_index_;
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
/**
* 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_;
/**
* Optional wrapper for node execution functions.
*/
const NodeExecuteWrapper *node_execute_wrapper_;
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
/**
* When a graph is executed, various things have to be allocated (e.g. the state of all nodes).
* Instead of doing many small allocations, a single bigger allocation is done. This struct
* contains the preprocessed offsets into that bigger buffer.
*/
struct {
int node_states_array_offset;
int loaded_inputs_array_offset;
Array<int> node_states_offsets;
int total_size;
} init_buffer_info_;
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
friend class Executor;
public:
GraphExecutor(const Graph &graph,
Vector<const GraphInputSocket *> graph_inputs,
Vector<const GraphOutputSocket *> graph_outputs,
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
const Logger *logger,
const SideEffectProvider *side_effect_provider,
const NodeExecuteWrapper *node_execute_wrapper);
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
void *init_storage(LinearAllocator<> &allocator) const override;
void destruct_storage(void *storage) const override;
std::string input_name(int index) const override;
std::string output_name(int index) const override;
Geometry Nodes: new evaluation system This refactors the geometry nodes evaluation system. No changes for the user are expected. At a high level the goals are: * Support using geometry nodes outside of the geometry nodes modifier. * Support using the evaluator infrastructure for other purposes like field evaluation. * Support more nodes, especially when many of them are disabled behind switch nodes. * Support doing preprocessing on node groups. For more details see T98492. There are fairly detailed comments in the code, but here is a high level overview for how it works now: * There is a new "lazy-function" system. It is similar in spirit to the multi-function system but with different goals. Instead of optimizing throughput for highly parallelizable work, this system is designed to compute only the data that is actually necessary. What data is necessary can be determined dynamically during evaluation. Many lazy-functions can be composed in a graph to form a new lazy-function, which can again be used in a graph etc. * Each geometry node group is converted into a lazy-function graph prior to evaluation. To evaluate geometry nodes, one then just has to evaluate that graph. Node groups are no longer inlined into their parents. Next steps for the evaluation system is to reduce the use of threads in some situations to avoid overhead. Many small node groups don't benefit from multi-threading at all. This is much easier to do now because not everything has to be inlined in one huge node tree anymore. Differential Revision: https://developer.blender.org/D15914
2022-09-13 08:44:26 +02:00
private:
void execute_impl(Params &params, const Context &context) const override;
};
} // namespace blender::fn::lazy_function