[Bf-blender-cvs] [17197430661] geometry-nodes: Geometry Nodes: improve node group evaluation
Jacques Lucke
noreply at git.blender.org
Fri Oct 23 15:14:11 CEST 2020
Commit: 17197430661c6accfe55bfbc756f9ee1beb95fc2
Author: Jacques Lucke
Date: Fri Oct 23 15:09:55 2020 +0200
Branches: geometry-nodes
https://developer.blender.org/rB17197430661c6accfe55bfbc756f9ee1beb95fc2
Geometry Nodes: improve node group evaluation
This adds support for nodes that have a multi-function implementation.
That includes various function nodes like Math, Combine Vector, ...
Furthermore, there is support for implicit conversions now. So it should
work when one connects e.g. a float to an integer and vice versa.
===================================================================
M source/blender/modifiers/intern/MOD_nodes.cc
M source/blender/nodes/NOD_node_tree_multi_function.hh
M source/blender/nodes/intern/node_tree_multi_function.cc
M source/blender/nodes/intern/type_callbacks.cc
===================================================================
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index 11254896461..38712054f22 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -65,6 +65,7 @@
#include "NOD_derived_node_tree.hh"
#include "NOD_geometry_exec.hh"
+#include "NOD_node_tree_multi_function.hh"
#include "NOD_type_callbacks.hh"
using blender::float3;
@@ -117,91 +118,186 @@ using namespace blender::nodes;
using namespace blender::fn;
using namespace blender::bke;
-static bool compute_input_socket(const DOutputSocket *group_input,
- GeometryPtr &group_input_geometry,
- const DInputSocket &socket_to_compute,
- void *r_value);
-
-static bool compute_output_socket(const DOutputSocket *group_input,
- GeometryPtr &group_input_geometry,
- const DOutputSocket &socket_to_compute,
- void *r_value)
-{
- if (group_input == &socket_to_compute) {
- new (r_value) GeometryPtr(group_input_geometry);
- return true;
+class GeometryNodesEvaluator {
+ private:
+ LinearAllocator<> allocator_;
+ const DerivedNodeTree &tree_;
+ Map<const DOutputSocket *, GMutablePointer> group_input_data_;
+ Vector<const DInputSocket *> group_outputs_;
+ MultiFunctionByNode &mf_by_node_;
+ const DataTypeConversions &conversions_;
+
+ public:
+ GeometryNodesEvaluator(const DerivedNodeTree &tree,
+ Map<const DOutputSocket *, GMutablePointer> group_input_data,
+ Vector<const DInputSocket *> group_outputs,
+ MultiFunctionByNode &mf_by_node)
+ : tree_(tree),
+ group_input_data_(std::move(group_input_data)),
+ group_outputs_(std::move(group_outputs)),
+ mf_by_node_(mf_by_node),
+ conversions_(get_implicit_type_conversions())
+ {
}
- const DNode &node = socket_to_compute.node();
- bNode *bnode = node.node_ref().bnode();
-
- LinearAllocator<> allocator;
- GValueByName node_inputs{allocator};
-
- /* Compute all inputs for the node. */
- for (const DInputSocket *input_socket : node.inputs()) {
- const CPPType &type = *socket_cpp_type_get(*input_socket->bsocket()->typeinfo);
- void *buffer = allocator.allocate(type.size(), type.alignment());
- compute_input_socket(group_input, group_input_geometry, *input_socket, buffer);
- node_inputs.move_in(input_socket->bsocket()->identifier, GMutablePointer{type, buffer});
- type.destruct(buffer);
+ Vector<GMutablePointer> execute()
+ {
+ Vector<GMutablePointer> results;
+ for (const DInputSocket *group_output : group_outputs_) {
+ const CPPType &type = *socket_cpp_type_get(*group_output->typeinfo());
+ void *result_buffer = allocator_.allocate(type.size(), type.alignment());
+ this->compute_input_socket(*group_output, result_buffer);
+ results.append(GMutablePointer{type, result_buffer});
+ }
+ for (GMutablePointer value : group_input_data_.values()) {
+ value.type()->destruct(value.get());
+ }
+ return results;
}
- /* Execute the node itself. */
- GValueByName node_outputs{allocator};
- bnode->typeinfo->geometry_node_execute(bnode, node_inputs, node_outputs);
-
- /* Pass relevant value to the caller. */
- bNodeSocket *bsocket_to_compute = socket_to_compute.bsocket();
- const CPPType &type_to_compute = *socket_cpp_type_get(*bsocket_to_compute->typeinfo);
- GMutablePointer computed_value = node_outputs.extract(bsocket_to_compute->identifier);
- type_to_compute.relocate_to_uninitialized(computed_value.get(), r_value);
- return true;
-}
-
-/* Returns true on success. */
-static bool compute_input_socket(const DOutputSocket *group_input,
- GeometryPtr &group_input_geometry,
- const DInputSocket &socket_to_compute,
- void *r_value)
-{
- Span<const DOutputSocket *> from_sockets = socket_to_compute.linked_sockets();
- Span<const DGroupInput *> from_group_inputs = socket_to_compute.linked_group_inputs();
- const int total_inputs = from_sockets.size() + from_group_inputs.size();
- if (total_inputs >= 2) {
- return false;
+ private:
+ void compute_input_socket(const DInputSocket &socket_to_compute, void *r_value)
+ {
+ Span<const DOutputSocket *> from_sockets = socket_to_compute.linked_sockets();
+ Span<const DGroupInput *> from_group_inputs = socket_to_compute.linked_group_inputs();
+ const int total_inputs = from_sockets.size() + from_group_inputs.size();
+ BLI_assert(total_inputs <= 1);
+
+ if (total_inputs == 0) {
+ bNodeSocket &bsocket = *socket_to_compute.bsocket();
+ socket_cpp_value_get(bsocket, r_value);
+ return;
+ }
+ if (from_group_inputs.size() == 1) {
+ bNodeSocket &bsocket = *from_group_inputs[0]->bsocket();
+ socket_cpp_value_get(bsocket, r_value);
+ return;
+ }
+
+ const DOutputSocket &from_socket = *from_sockets[0];
+ const CPPType &from_type = *socket_cpp_type_get(*from_socket.typeinfo());
+ const CPPType &to_type = *socket_cpp_type_get(*socket_to_compute.typeinfo());
+ if (from_type == to_type) {
+ this->compute_output_socket(from_socket, r_value);
+ }
+ else {
+ /* The type of both sockets don't match, so a conversion is necessary. */
+ if (conversions_.is_convertible(from_type, to_type)) {
+ void *from_value = allocator_.allocate(from_type.size(), from_type.alignment());
+ this->compute_output_socket(from_socket, from_value);
+ conversions_.convert(from_type, to_type, from_value, r_value);
+ from_type.destruct(from_value);
+ }
+ else {
+ /* Use a default value when the types cannot be converted. */
+ to_type.copy_to_uninitialized(to_type.default_value(), r_value);
+ }
+ }
}
- if (total_inputs == 0) {
- bNodeSocket *bsocket = socket_to_compute.bsocket();
- socket_cpp_value_get(*bsocket, r_value);
- return true;
- }
- if (from_group_inputs.size() == 1) {
- bNodeSocket *bsocket = from_group_inputs[0]->bsocket();
- BLI_assert(bsocket->type == socket_to_compute.bsocket()->type);
- socket_cpp_value_get(*bsocket, r_value);
- return true;
+
+ void compute_output_socket(const DOutputSocket &socket_to_compute, void *r_value)
+ {
+ const GMutablePointer *group_input = group_input_data_.lookup_ptr(&socket_to_compute);
+ if (group_input != nullptr) {
+ const CPPType &type = *group_input->type();
+ type.copy_to_uninitialized(group_input->get(), r_value);
+ return;
+ }
+
+ const DNode &node = socket_to_compute.node();
+ GValueByName node_inputs{allocator_};
+
+ /* Compute all inputs for the node. */
+ for (const DInputSocket *input_socket : node.inputs()) {
+ const CPPType &type = *socket_cpp_type_get(*input_socket->typeinfo());
+ void *buffer = allocator_.allocate(type.size(), type.alignment());
+ compute_input_socket(*input_socket, buffer);
+ node_inputs.move_in(input_socket->identifier(), GMutablePointer{type, buffer});
+ type.destruct(buffer);
+ }
+
+ /* Execute the node itself. */
+ GValueByName node_outputs{allocator_};
+ this->execute_node(node, node_inputs, node_outputs);
+
+ /* Pass relevant value to the caller. */
+ bNodeSocket *bsocket_to_compute = socket_to_compute.bsocket();
+ const CPPType &type_to_compute = *socket_cpp_type_get(*bsocket_to_compute->typeinfo);
+ GMutablePointer computed_value = node_outputs.extract(bsocket_to_compute->identifier);
+ type_to_compute.relocate_to_uninitialized(computed_value.get(), r_value);
}
- const DOutputSocket &from_socket = *from_sockets[0];
- return compute_output_socket(group_input, group_input_geometry, from_socket, r_value);
-}
+ void execute_node(const DNode &node, GValueByName &node_inputs, GValueByName &node_outputs)
+ {
+ bNode *bnode = node.bnode();
+ if (bnode->typeinfo->geometry_node_execute != nullptr) {
+ bnode->typeinfo->geometry_node_execute(bnode, node_inputs, node_outputs);
+ return;
+ }
+
+ /* Use the multi-function implementation of the node. */
+ const MultiFunction &fn = *mf_by_node_.lookup(&node);
+ MFContextBuilder context;
+ MFParamsBuilder params{fn, 1};
+ Vector<GMutablePointer> input_data;
+ for (const DInputSocket *dsocket : node.inputs()) {
+ if (dsocket->is_available()) {
+ GMutablePointer data = node_inputs.extract(dsocket->identifier());
+ params.add_readonly_single_input(GSpan(*data.type(), data.get(), 1));
+ input_data.append(data);
+ }
+ }
+ Vector<GMutablePointer> output_data;
+ for (const DOutputSocket *dsocket : node.outputs()) {
+ if (dsocket->is_available()) {
+ const CPPType &type = *socket_cpp_type_get(*dsocket->typeinfo());
+ void *buffer = allocator_.allocate(type.size(), type.alignment());
+ params.add_uninitialized_single_output(GMutableSpan(type, buffer, 1));
+ output_data.append(GMutablePointer(type, buffer));
+ }
+ }
+ fn.call(IndexRange(1), params, context);
+ for (GMutablePointer value : input_data) {
+ value.destruct();
+ }
+ for (const int i : node.outputs().index_range()) {
+ GMutablePointer value = output_data[i];
+ node_outputs.move_in(node.output(i).identifier(), value);
+ value.destruct();
+ }
+ }
+};
/**
* Evaluate a node group to compute the output geometry.
* Currently, this uses a fairly basic and inefficient algorithm that might compute things more
* often than necessary. It's going to be replaced soon.
*/
-static GeometryPtr compute_geometry(const DOutputSocket *group_input,
- GeometryPtr &group_input_geometry,
+static GeometryPtr compute_geometry(const DerivedNodeTree &tree,
+ const DOutputSocket *group_input,
+ GeometryPtr group_input_geometry,
const DInputSocket &socket_to_compute)
{
- Geom
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list