Blender  V2.93
node_tree_multi_function.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
18 #include "NOD_type_conversions.hh"
19 
21 
22 #include "BLI_color.hh"
23 #include "BLI_float2.hh"
24 #include "BLI_float3.hh"
25 
26 namespace blender::nodes {
27 
29 {
30  Vector<fn::MFDataType, 10> input_types;
31  Vector<fn::MFDataType, 10> output_types;
32 
33  for (const InputSocketRef *dsocket : dnode_->inputs()) {
34  if (dsocket->is_available()) {
35  std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->typeinfo());
36  if (data_type.has_value()) {
37  input_types.append(*data_type);
38  }
39  }
40  }
41  for (const OutputSocketRef *dsocket : dnode_->outputs()) {
42  if (dsocket->is_available()) {
43  std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->typeinfo());
44  if (data_type.has_value()) {
45  output_types.append(*data_type);
46  }
47  }
48  }
49 
50  const fn::MultiFunction &fn = this->construct_fn<fn::CustomMF_DefaultOutput>(
51  name, input_types, output_types);
52  return fn;
53 }
54 
55 static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &dnode)
56 {
57  constexpr int stack_capacity = 10;
58 
62 
63  for (const InputSocketRef *dsocket : dnode->inputs()) {
64  if (dsocket->is_available()) {
65  std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
66  if (data_type.has_value()) {
67  input_types.append(*data_type);
68  input_names.append(dsocket->name());
69  input_dsockets.append(dsocket);
70  }
71  }
72  }
73 
77 
78  for (const OutputSocketRef *dsocket : dnode->outputs()) {
79  if (dsocket->is_available()) {
80  std::optional<fn::MFDataType> data_type = socket_mf_type_get(*dsocket->bsocket()->typeinfo);
81  if (data_type.has_value()) {
82  output_types.append(*data_type);
83  output_names.append(dsocket->name());
84  output_dsockets.append(dsocket);
85  }
86  }
87  }
88 
89  fn::MFDummyNode &dummy_node = common.network.add_dummy(
90  dnode->name(), input_types, output_types, input_names, output_names);
91 
92  common.network_map.add(*dnode.context(), input_dsockets, dummy_node.inputs());
93  common.network_map.add(*dnode.context(), output_dsockets, dummy_node.outputs());
94 }
95 
96 static bool has_data_sockets(const DNode &dnode)
97 {
98  for (const InputSocketRef *socket : dnode->inputs()) {
99  if (socket_is_mf_data_socket(*socket->bsocket()->typeinfo)) {
100  return true;
101  }
102  }
103  for (const OutputSocketRef *socket : dnode->outputs()) {
104  if (socket_is_mf_data_socket(*socket->bsocket()->typeinfo)) {
105  return true;
106  }
107  }
108  return false;
109 }
110 
112  FunctionRef<void(DNode)> callback)
113 {
114  common.tree.foreach_node([&](const DNode dnode) {
115  if (dnode->is_group_node()) {
116  return;
117  }
118  /* Don't insert non-root group input/output nodes, because they will be inlined. */
119  if (!dnode.context()->is_root()) {
120  if (dnode->is_group_input_node() || dnode->is_group_output_node()) {
121  return;
122  }
123  }
124  callback(dnode);
125  });
126 }
127 
133 {
134  foreach_node_to_insert(common, [&](const DNode dnode) {
135  const bNodeType *node_type = dnode->typeinfo();
136  if (node_type->expand_in_mf_network != nullptr) {
137  NodeMFNetworkBuilder builder{common, dnode};
138  node_type->expand_in_mf_network(builder);
139  }
140  else if (has_data_sockets(dnode)) {
141  insert_dummy_node(common, dnode);
142  }
143  });
144 }
145 
148 {
149  const fn::MultiFunction *default_fn;
150  if (type.is_single()) {
151  default_fn = &common.scope.construct<fn::CustomMF_GenericConstant>(
152  AT, type.single_type(), type.single_type().default_value());
153  }
154  else {
155  default_fn = &common.scope.construct<fn::CustomMF_GenericConstantArray>(
156  AT, fn::GSpan(type.vector_base_type()));
157  }
158 
159  fn::MFNode &node = common.network.add_function(*default_fn);
160  return node.output(0);
161 }
162 
164  const DInputSocket &dsocket)
165 {
167 
168  SocketMFNetworkBuilder builder{common, dsocket};
170 
171  fn::MFOutputSocket *built_socket = builder.built_socket();
172  BLI_assert(built_socket != nullptr);
173  return built_socket;
174 }
175 
177 {
178  foreach_node_to_insert(common, [&](const DNode dnode) {
179  for (const InputSocketRef *socket_ref : dnode->inputs()) {
180  const DInputSocket to_dsocket{dnode.context(), socket_ref};
181  if (!to_dsocket->is_available()) {
182  continue;
183  }
184  if (!socket_is_mf_data_socket(*to_dsocket->typeinfo())) {
185  continue;
186  }
187 
188  Span<fn::MFInputSocket *> to_sockets = common.network_map.lookup(to_dsocket);
189  BLI_assert(to_sockets.size() >= 1);
190  const fn::MFDataType to_type = to_sockets[0]->data_type();
191 
192  Vector<DSocket> from_dsockets;
193  to_dsocket.foreach_origin_socket([&](DSocket socket) { from_dsockets.append(socket); });
194  if (from_dsockets.size() > 1) {
195  fn::MFOutputSocket &from_socket = insert_default_value_for_type(common, to_type);
196  for (fn::MFInputSocket *to_socket : to_sockets) {
197  common.network.add_link(from_socket, *to_socket);
198  }
199  continue;
200  }
201  if (from_dsockets.is_empty()) {
202  /* The socket is not linked. Need to use the value of the socket itself. */
203  fn::MFOutputSocket *built_socket = insert_unlinked_input(common, to_dsocket);
204  for (fn::MFInputSocket *to_socket : to_sockets) {
205  common.network.add_link(*built_socket, *to_socket);
206  }
207  continue;
208  }
209  if (from_dsockets[0]->is_input()) {
210  DInputSocket from_dsocket{from_dsockets[0]};
211  fn::MFOutputSocket *built_socket = insert_unlinked_input(common, from_dsocket);
212  for (fn::MFInputSocket *to_socket : to_sockets) {
213  common.network.add_link(*built_socket, *to_socket);
214  }
215  continue;
216  }
217  DOutputSocket from_dsocket{from_dsockets[0]};
218  fn::MFOutputSocket *from_socket = &common.network_map.lookup(from_dsocket);
219  const fn::MFDataType from_type = from_socket->data_type();
220 
221  if (from_type != to_type) {
222  const fn::MultiFunction *conversion_fn =
224  if (conversion_fn != nullptr) {
225  fn::MFNode &node = common.network.add_function(*conversion_fn);
226  common.network.add_link(*from_socket, node.input(0));
227  from_socket = &node.output(0);
228  }
229  else {
230  from_socket = &insert_default_value_for_type(common, to_type);
231  }
232  }
233 
234  for (fn::MFInputSocket *to_socket : to_sockets) {
235  common.network.add_link(*from_socket, *to_socket);
236  }
237  }
238  });
239 }
240 
249  const DerivedNodeTree &tree,
250  ResourceScope &scope)
251 {
252  MFNetworkTreeMap network_map{tree, network};
253 
254  CommonMFNetworkBuilderData common{scope, network, network_map, tree};
255 
256  insert_nodes(common);
258 
259  return network_map;
260 }
261 
266 enum class NodeExpandType {
270 };
271 
277  const DNode &dnode,
278  const fn::MultiFunction **r_single_function)
279 {
280  const fn::MFFunctionNode *single_function_node = nullptr;
281  bool has_multiple_nodes = false;
282  bool has_dummy_nodes = false;
283 
284  auto check_mf_node = [&](fn::MFNode &mf_node) {
285  if (mf_node.is_function()) {
286  if (single_function_node == nullptr) {
287  single_function_node = &mf_node.as_function();
288  }
289  if (&mf_node != single_function_node) {
290  has_multiple_nodes = true;
291  }
292  }
293  else {
294  BLI_assert(mf_node.is_dummy());
295  has_dummy_nodes = true;
296  }
297  };
298 
299  for (const InputSocketRef *dsocket : dnode->inputs()) {
300  if (dsocket->is_available()) {
301  for (fn::MFInputSocket *mf_input :
302  network_map.lookup(DInputSocket(dnode.context(), dsocket))) {
303  check_mf_node(mf_input->node());
304  }
305  }
306  }
307  for (const OutputSocketRef *dsocket : dnode->outputs()) {
308  if (dsocket->is_available()) {
309  fn::MFOutputSocket &mf_output = network_map.lookup(DOutputSocket(dnode.context(), dsocket));
310  check_mf_node(mf_output.node());
311  }
312  }
313 
314  if (has_dummy_nodes) {
315  return NodeExpandType::HasDummyNodes;
316  }
317  if (has_multiple_nodes) {
318  return NodeExpandType::MultipleFunctionNodes;
319  }
320  *r_single_function = &single_function_node->function();
321  return NodeExpandType::SingleFunctionNode;
322 }
323 
325  const DNode &dnode,
326  fn::MFNetwork &network,
327  MFNetworkTreeMap &network_map,
328  ResourceScope &scope)
329 {
330  Vector<const fn::MFOutputSocket *> dummy_fn_inputs;
331  for (const InputSocketRef *dsocket : dnode->inputs()) {
332  if (dsocket->is_available()) {
333  MFDataType data_type = *socket_mf_type_get(*dsocket->typeinfo());
334  fn::MFOutputSocket &fn_input = network.add_input(data_type.to_string(), data_type);
335  for (fn::MFInputSocket *mf_input :
336  network_map.lookup(DInputSocket(dnode.context(), dsocket))) {
337  network.add_link(fn_input, *mf_input);
338  dummy_fn_inputs.append(&fn_input);
339  }
340  }
341  }
342  Vector<const fn::MFInputSocket *> dummy_fn_outputs;
343  for (const OutputSocketRef *dsocket : dnode->outputs()) {
344  if (dsocket->is_available()) {
345  fn::MFOutputSocket &mf_output = network_map.lookup(DOutputSocket(dnode.context(), dsocket));
346  MFDataType data_type = mf_output.data_type();
347  fn::MFInputSocket &fn_output = network.add_output(data_type.to_string(), data_type);
348  network.add_link(mf_output, fn_output);
349  dummy_fn_outputs.append(&fn_output);
350  }
351  }
352 
354  __func__, std::move(dummy_fn_inputs), std::move(dummy_fn_outputs));
355  return fn_evaluator;
356 }
357 
363 {
364  /* Build a network that nodes can insert themselves into. However, the individual nodes are not
365  * connected. */
366  fn::MFNetwork &network = scope.construct<fn::MFNetwork>(__func__);
367  MFNetworkTreeMap network_map{tree, network};
368  MultiFunctionByNode functions_by_node;
369 
370  CommonMFNetworkBuilderData common{scope, network, network_map, tree};
371 
372  tree.foreach_node([&](DNode dnode) {
373  const bNodeType *node_type = dnode->typeinfo();
374  if (node_type->expand_in_mf_network == nullptr) {
375  /* This node does not have a multi-function implementation. */
376  return;
377  }
378 
379  NodeMFNetworkBuilder builder{common, dnode};
380  node_type->expand_in_mf_network(builder);
381 
382  const fn::MultiFunction *single_function = nullptr;
383  const NodeExpandType expand_type = get_node_expand_type(network_map, dnode, &single_function);
384 
385  switch (expand_type) {
386  case NodeExpandType::HasDummyNodes: {
387  /* Dummy nodes cannot be executed, so skip them. */
388  break;
389  }
390  case NodeExpandType::SingleFunctionNode: {
391  /* This is the common case. Most nodes just expand to a single function. */
392  functions_by_node.add_new(dnode, single_function);
393  break;
394  }
395  case NodeExpandType::MultipleFunctionNodes: {
396  /* If a node expanded into multiple functions, a new function has to be created that
397  * combines those. */
399  dnode, network, network_map, scope);
400  functions_by_node.add_new(dnode, &fn);
401  break;
402  }
403  }
404  });
405 
406  return functions_by_node;
407 }
408 
409 } // namespace blender::nodes
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define AT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void add_new(const Key &key, const Value &value)
Definition: BLI_map.hh:234
T & construct(const char *name, Args &&... args)
void append(const T &value)
Definition: BLI_vector.hh:438
const MultiFunction & function() const
MFDummyNode & add_dummy(StringRef name, Span< MFDataType > input_types, Span< MFDataType > output_types, Span< StringRef > input_names, Span< StringRef > output_names)
void add_link(MFOutputSocket &from, MFInputSocket &to)
MFFunctionNode & add_function(const MultiFunction &function)
MFOutputSocket & add_input(StringRef name, MFDataType data_type)
MFInputSocket & add_output(StringRef name, MFDataType data_type)
Span< MFInputSocket * > inputs()
Span< MFOutputSocket * > outputs()
const MFDataType & data_type() const
const DTreeContext * context() const
const fn::MultiFunction * get_conversion_multi_function(fn::MFDataType from, fn::MFDataType to) const
void foreach_node(FunctionRef< void(DNode)> callback) const
void add(const DSocket &dsocket, fn::MFSocket &socket)
fn::MFOutputSocket & lookup(const DOutputSocket &dsocket)
const fn::MultiFunction & get_default_fn(StringRef name)
bNodeType * typeinfo() const
Span< const InputSocketRef * > inputs() const
Span< const OutputSocketRef * > outputs() const
StringRefNull name() const
bNodeSocketType * typeinfo() const
OperationNode * node
DEGForeachIDComponentCallback callback
void * tree
void socket_expand_in_mf_network(SocketMFNetworkBuilder &builder)
static void foreach_node_to_insert(CommonMFNetworkBuilderData &common, FunctionRef< void(DNode)> callback)
std::optional< MFDataType > socket_mf_type_get(const bNodeSocketType &stype)
bool socket_is_mf_data_socket(const bNodeSocketType &stype)
MultiFunctionByNode get_multi_function_per_node(const DerivedNodeTree &tree, ResourceScope &scope)
const DataTypeConversions & get_implicit_type_conversions()
static void insert_nodes(CommonMFNetworkBuilderData &common)
MFNetworkTreeMap insert_node_tree_into_mf_network(fn::MFNetwork &network, const DerivedNodeTree &tree, ResourceScope &scope)
static bool has_data_sockets(const DNode &dnode)
static void insert_dummy_node(CommonMFNetworkBuilderData &common, const DNode &dnode)
static const fn::MultiFunction & create_function_for_node_that_expands_into_multiple(const DNode &dnode, fn::MFNetwork &network, MFNetworkTreeMap &network_map, ResourceScope &scope)
static void insert_links_and_unlinked_inputs(CommonMFNetworkBuilderData &common)
static NodeExpandType get_node_expand_type(MFNetworkTreeMap &network_map, const DNode &dnode, const fn::MultiFunction **r_single_function)
static fn::MFOutputSocket * insert_unlinked_input(CommonMFNetworkBuilderData &common, const DInputSocket &dsocket)
static fn::MFOutputSocket & insert_default_value_for_type(CommonMFNetworkBuilderData &common, fn::MFDataType type)
Defines a node type.
Definition: BKE_node.h:221
NodeExpandInMFNetworkFunction expand_in_mf_network
Definition: BKE_node.h:324