Blender  V3.3
FN_field.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
35 #include "BLI_function_ref.hh"
37 #include "BLI_string_ref.hh"
38 #include "BLI_vector.hh"
39 #include "BLI_vector_set.hh"
40 
41 #include "FN_multi_function.hh"
42 
43 namespace blender::fn {
44 
45 class FieldInput;
46 struct FieldInputs;
47 
52 enum class FieldNodeType {
53  Input,
54  Operation,
55  Constant,
56 };
57 
61 class FieldNode {
62  private:
63  FieldNodeType node_type_;
64 
65  protected:
72  std::shared_ptr<const FieldInputs> field_inputs_;
73 
74  public:
76  virtual ~FieldNode();
77 
78  virtual const CPPType &output_cpp_type(int output_index) const = 0;
79 
80  FieldNodeType node_type() const;
81  bool depends_on_input() const;
82 
83  const std::shared_ptr<const FieldInputs> &field_inputs() const;
84 
85  virtual uint64_t hash() const;
86  virtual bool is_equal_to(const FieldNode &other) const;
87 };
88 
92 template<typename NodePtr> class GFieldBase {
93  protected:
94  NodePtr node_ = nullptr;
96 
97  GFieldBase(NodePtr node, const int node_output_index)
99  {
100  }
101 
102  public:
103  GFieldBase() = default;
104 
105  operator bool() const
106  {
107  return node_ != nullptr;
108  }
109 
110  friend bool operator==(const GFieldBase &a, const GFieldBase &b)
111  {
112  /* Two nodes can compare equal even when their pointer is not the same. For example, two
113  * "Position" nodes are the same. */
114  return *a.node_ == *b.node_ && a.node_output_index_ == b.node_output_index_;
115  }
116 
117  uint64_t hash() const
118  {
120  }
121 
122  const CPPType &cpp_type() const
123  {
124  return node_->output_cpp_type(node_output_index_);
125  }
126 
127  const FieldNode &node() const
128  {
129  return *node_;
130  }
131 
132  int node_output_index() const
133  {
134  return node_output_index_;
135  }
136 };
137 
141 class GField : public GFieldBase<std::shared_ptr<FieldNode>> {
142  public:
143  GField() = default;
144 
145  GField(std::shared_ptr<FieldNode> node, const int node_output_index = 0)
146  : GFieldBase<std::shared_ptr<FieldNode>>(std::move(node), node_output_index)
147  {
148  }
149 };
150 
155 class GFieldRef : public GFieldBase<const FieldNode *> {
156  public:
157  GFieldRef() = default;
158 
159  GFieldRef(const GField &field)
160  : GFieldBase<const FieldNode *>(&field.node(), field.node_output_index())
161  {
162  }
163 
164  GFieldRef(const FieldNode &node, const int node_output_index = 0)
166  {
167  }
168 };
169 
170 namespace detail {
171 /* Utility class to make #is_field_v work. */
173 };
174 } // namespace detail
175 
179 template<typename T> class Field : public GField, detail::TypedFieldBase {
180  public:
181  using base_type = T;
182 
183  Field() = default;
184 
185  Field(GField field) : GField(std::move(field))
186  {
187  BLI_assert(this->cpp_type().template is<T>());
188  }
189 
190  Field(std::shared_ptr<FieldNode> node, const int node_output_index = 0)
192  {
193  }
194 };
195 
197 template<typename T>
198 static constexpr bool is_field_v = std::is_base_of_v<detail::TypedFieldBase, T> &&
199  !std::is_same_v<detail::TypedFieldBase, T>;
200 
204 class FieldOperation : public FieldNode {
209  std::shared_ptr<const MultiFunction> owned_function_;
210  const MultiFunction *function_;
211 
213  blender::Vector<GField> inputs_;
214 
215  public:
216  FieldOperation(std::shared_ptr<const MultiFunction> function, Vector<GField> inputs = {});
217  FieldOperation(const MultiFunction &function, Vector<GField> inputs = {});
219 
220  Span<GField> inputs() const;
221  const MultiFunction &multi_function() const;
222 
223  const CPPType &output_cpp_type(int output_index) const override;
224 
225  static std::shared_ptr<FieldOperation> Create(std::shared_ptr<const MultiFunction> function,
226  Vector<GField> inputs = {})
227  {
228  return std::make_shared<FieldOperation>(FieldOperation(std::move(function), inputs));
229  }
230  static std::shared_ptr<FieldOperation> Create(const MultiFunction &function,
231  Vector<GField> inputs = {})
232  {
233  return std::make_shared<FieldOperation>(FieldOperation(function, inputs));
234  }
235 };
236 
237 class FieldContext;
238 
242 class FieldInput : public FieldNode {
243  public:
244  /* The order is also used for sorting in socket inspection. */
245  enum class Category {
246  NamedAttribute = 0,
247  Generated = 1,
248  AnonymousAttribute = 2,
249  Unknown,
250  };
251 
252  protected:
253  const CPPType *type_;
254  std::string debug_name_;
256 
257  public:
258  FieldInput(const CPPType &type, std::string debug_name = "");
260 
266  IndexMask mask,
267  ResourceScope &scope) const = 0;
268 
269  virtual std::string socket_inspection_name() const;
271  const CPPType &cpp_type() const;
272  Category category() const;
273 
274  const CPPType &output_cpp_type(int output_index) const override;
275 };
276 
277 class FieldConstant : public FieldNode {
278  private:
279  const CPPType &type_;
280  void *value_;
281 
282  public:
283  FieldConstant(const CPPType &type, const void *value);
284  ~FieldConstant();
285 
286  const CPPType &output_cpp_type(int output_index) const override;
287  const CPPType &type() const;
288  GPointer value() const;
289 };
290 
294 struct FieldInputs {
302 };
303 
308  public:
309  virtual ~FieldContext() = default;
310 
311  virtual GVArray get_varray_for_input(const FieldInput &field_input,
312  IndexMask mask,
313  ResourceScope &scope) const;
314 };
315 
320  private:
321  struct OutputPointerInfo {
322  void *dst = nullptr;
323  /* When a destination virtual array is provided for an input, this is
324  * unnecessary, otherwise this is used to construct the required virtual array. */
325  void (*set)(void *dst, const GVArray &varray, ResourceScope &scope) = nullptr;
326  };
327 
328  ResourceScope scope_;
329  const FieldContext &context_;
330  const IndexMask mask_;
331  Vector<GField> fields_to_evaluate_;
332  Vector<GVMutableArray> dst_varrays_;
333  Vector<GVArray> evaluated_varrays_;
334  Vector<OutputPointerInfo> output_pointer_infos_;
335  bool is_evaluated_ = false;
336 
337  Field<bool> selection_field_;
338  IndexMask selection_mask_;
339 
340  public:
343  : context_(context), mask_(*mask)
344  {
345  }
346 
348  FieldEvaluator(const FieldContext &context, const int64_t size) : context_(context), mask_(size)
349  {
350  }
351 
353  {
354  /* While this assert isn't strictly necessary, and could be replaced with a warning,
355  * it will catch cases where someone forgets to call #evaluate(). */
356  BLI_assert(is_evaluated_);
357  }
358 
366  void set_selection(Field<bool> selection)
367  {
368  selection_field_ = std::move(selection);
369  }
370 
376 
378  template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst)
379  {
380  return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst)));
381  }
382 
389  int add_with_destination(GField field, GMutableSpan dst);
390 
397  template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst)
398  {
399  return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst));
400  }
401 
402  int add(GField field, GVArray *varray_ptr);
403 
410  template<typename T> int add(Field<T> field, VArray<T> *varray_ptr)
411  {
412  const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field));
413  dst_varrays_.append({});
414  output_pointer_infos_.append(OutputPointerInfo{
415  varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) {
416  *(VArray<T> *)dst = varray.typed<T>();
417  }});
418  return field_index;
419  }
420 
424  int add(GField field);
425 
429  void evaluate();
430 
431  const GVArray &get_evaluated(const int field_index) const
432  {
433  BLI_assert(is_evaluated_);
434  return evaluated_varrays_[field_index];
435  }
436 
437  template<typename T> VArray<T> get_evaluated(const int field_index)
438  {
439  return this->get_evaluated(field_index).typed<T>();
440  }
441 
443 
449  IndexMask get_evaluated_as_mask(int field_index);
450 };
451 
471  Span<GFieldRef> fields_to_evaluate,
472  IndexMask mask,
473  const FieldContext &context,
474  Span<GVMutableArray> dst_varrays = {});
475 
476 /* -------------------------------------------------------------------- */
480 void evaluate_constant_field(const GField &field, void *r_value);
481 
482 template<typename T> T evaluate_constant_field(const Field<T> &field)
483 {
484  T value;
485  value.~T();
486  evaluate_constant_field(field, &value);
487  return value;
488 }
489 
490 Field<bool> invert_boolean_field(const Field<bool> &field);
491 
492 GField make_constant_field(const CPPType &type, const void *value);
493 
494 template<typename T> Field<T> make_constant_field(T value)
495 {
496  return make_constant_field(CPPType::get<T>(), &value);
497 }
498 
508 GField make_field_constant_if_possible(GField field);
509 
511  public:
512  IndexFieldInput();
513 
515 
517  IndexMask mask,
518  ResourceScope &scope) const final;
519 
520  uint64_t hash() const override;
521  bool is_equal_to(const fn::FieldNode &other) const override;
522 };
523 
526 /* -------------------------------------------------------------------- */
532 template<typename T> struct ValueOrField {
534  T value{};
536 
537  ValueOrField() = default;
538 
540  {
541  }
542 
544  {
545  }
546 
547  bool is_field() const
548  {
549  return (bool)this->field;
550  }
551 
553  {
554  if (this->field) {
555  return this->field;
556  }
557  return make_constant_field(this->value);
558  }
559 
560  T as_value() const
561  {
562  if (this->field) {
563  /* This returns a default value when the field is not constant. */
564  return evaluate_constant_field(this->field);
565  }
566  return this->value;
567  }
568 };
569 
572 /* -------------------------------------------------------------------- */
576 inline FieldNode::FieldNode(const FieldNodeType node_type) : node_type_(node_type)
577 {
578 }
579 
581 {
582  return node_type_;
583 }
584 
585 inline bool FieldNode::depends_on_input() const
586 {
587  return field_inputs_ && !field_inputs_->nodes.is_empty();
588 }
589 
590 inline const std::shared_ptr<const FieldInputs> &FieldNode::field_inputs() const
591 {
592  return field_inputs_;
593 }
594 
595 inline uint64_t FieldNode::hash() const
596 {
597  return get_default_hash(this);
598 }
599 
600 inline bool FieldNode::is_equal_to(const FieldNode &other) const
601 {
602  return this == &other;
603 }
604 
605 inline bool operator==(const FieldNode &a, const FieldNode &b)
606 {
607  return a.is_equal_to(b);
608 }
609 
610 inline bool operator!=(const FieldNode &a, const FieldNode &b)
611 {
612  return !(a == b);
613 }
614 
617 /* -------------------------------------------------------------------- */
622 {
623  return inputs_;
624 }
625 
627 {
628  return *function_;
629 }
630 
631 inline const CPPType &FieldOperation::output_cpp_type(int output_index) const
632 {
633  int output_counter = 0;
634  for (const int param_index : function_->param_indices()) {
635  MFParamType param_type = function_->param_type(param_index);
636  if (param_type.is_output()) {
637  if (output_counter == output_index) {
638  return param_type.data_type().single_type();
639  }
640  output_counter++;
641  }
642  }
644  return CPPType::get<float>();
645 }
646 
649 /* -------------------------------------------------------------------- */
653 inline std::string FieldInput::socket_inspection_name() const
654 {
655  return debug_name_;
656 }
657 
659 {
660  return debug_name_;
661 }
662 
663 inline const CPPType &FieldInput::cpp_type() const
664 {
665  return *type_;
666 }
667 
669 {
670  return category_;
671 }
672 
673 inline const CPPType &FieldInput::output_cpp_type(int output_index) const
674 {
675  BLI_assert(output_index == 0);
676  UNUSED_VARS_NDEBUG(output_index);
677  return *type_;
678 }
679 
682 } // namespace blender::fn
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define final(a, b, c)
Definition: BLI_hash.h:21
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
_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
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
VArray< T > typed() const
int64_t append_and_get_index(const T &value)
Definition: BLI_vector.hh:452
void append(const T &value)
Definition: BLI_vector.hh:433
FieldConstant(const CPPType &type, const void *value)
Definition: field.cc:676
const CPPType & type() const
Definition: field.cc:696
const CPPType & output_cpp_type(int output_index) const override
Definition: field.cc:689
GPointer value() const
Definition: field.cc:701
virtual ~FieldContext()=default
virtual GVArray get_varray_for_input(const FieldInput &field_input, IndexMask mask, ResourceScope &scope) const
Definition: field.cc:535
VArray< T > get_evaluated(const int field_index)
Definition: FN_field.hh:437
IndexMask get_evaluated_selection_as_mask()
Definition: field.cc:797
FieldEvaluator(const FieldContext &context, const int64_t size)
Definition: FN_field.hh:348
FieldEvaluator(const FieldContext &context, const IndexMask *mask)
Definition: FN_field.hh:342
void set_selection(Field< bool > selection)
Definition: FN_field.hh:366
int add(GField field, GVArray *varray_ptr)
Definition: field.cc:731
IndexMask get_evaluated_as_mask(int field_index)
Definition: field.cc:784
int add(Field< T > field, VArray< T > *varray_ptr)
Definition: FN_field.hh:410
int add_with_destination(Field< T > field, MutableSpan< T > dst)
Definition: FN_field.hh:397
const GVArray & get_evaluated(const int field_index) const
Definition: FN_field.hh:431
int add_with_destination(GField field, GVMutableArray dst)
Definition: field.cc:718
int add_with_destination(Field< T > field, VMutableArray< T > dst)
Definition: FN_field.hh:378
FieldInput(const CPPType &type, std::string debug_name="")
Definition: field.cc:660
std::string debug_name_
Definition: FN_field.hh:254
virtual GVArray get_varray_for_context(const FieldContext &context, IndexMask mask, ResourceScope &scope) const =0
Category category() const
Definition: FN_field.hh:668
const CPPType * type_
Definition: FN_field.hh:253
const CPPType & cpp_type() const
Definition: FN_field.hh:663
virtual std::string socket_inspection_name() const
Definition: FN_field.hh:653
const CPPType & output_cpp_type(int output_index) const override
Definition: FN_field.hh:673
blender::StringRef debug_name() const
Definition: FN_field.hh:658
FieldNodeType node_type() const
Definition: FN_field.hh:580
std::shared_ptr< const FieldInputs > field_inputs_
Definition: FN_field.hh:72
virtual bool is_equal_to(const FieldNode &other) const
Definition: FN_field.hh:600
virtual const CPPType & output_cpp_type(int output_index) const =0
virtual uint64_t hash() const
Definition: FN_field.hh:595
FieldNode(FieldNodeType node_type)
Definition: FN_field.hh:576
bool depends_on_input() const
Definition: FN_field.hh:585
const std::shared_ptr< const FieldInputs > & field_inputs() const
Definition: FN_field.hh:590
const MultiFunction & multi_function() const
Definition: FN_field.hh:626
static std::shared_ptr< FieldOperation > Create(const MultiFunction &function, Vector< GField > inputs={})
Definition: FN_field.hh:230
Span< GField > inputs() const
Definition: FN_field.hh:621
static std::shared_ptr< FieldOperation > Create(std::shared_ptr< const MultiFunction > function, Vector< GField > inputs={})
Definition: FN_field.hh:225
const CPPType & output_cpp_type(int output_index) const override
Definition: FN_field.hh:631
FieldOperation(std::shared_ptr< const MultiFunction > function, Vector< GField > inputs={})
Definition: field.cc:585
Field(std::shared_ptr< FieldNode > node, const int node_output_index=0)
Definition: FN_field.hh:190
Field(GField field)
Definition: FN_field.hh:185
GFieldBase(NodePtr node, const int node_output_index)
Definition: FN_field.hh:97
const FieldNode & node() const
Definition: FN_field.hh:127
uint64_t hash() const
Definition: FN_field.hh:117
const CPPType & cpp_type() const
Definition: FN_field.hh:122
int node_output_index() const
Definition: FN_field.hh:132
friend bool operator==(const GFieldBase &a, const GFieldBase &b)
Definition: FN_field.hh:110
GFieldRef(const FieldNode &node, const int node_output_index=0)
Definition: FN_field.hh:164
GFieldRef(const GField &field)
Definition: FN_field.hh:159
GField(std::shared_ptr< FieldNode > node, const int node_output_index=0)
Definition: FN_field.hh:145
uint64_t hash() const override
Definition: field.cc:563
static GVArray get_index_varray(IndexMask mask)
Definition: field.cc:549
GVArray get_varray_for_context(const FieldContext &context, IndexMask mask, ResourceScope &scope) const final
bool is_equal_to(const fn::FieldNode &other) const override
Definition: field.cc:569
const CPPType & single_type() const
MFParamType param_type(int param_index) const
IndexRange param_indices() const
SyclQueue void void size_t num_bytes void
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
#define T
static unsigned a[3]
Definition: RandGen.cpp:78
bool operator==(const FieldNode &a, const FieldNode &b)
Definition: FN_field.hh:605
bool operator!=(const FieldNode &a, const FieldNode &b)
Definition: FN_field.hh:610
GField make_constant_field(const CPPType &type, const void *value)
Definition: field.cc:529
GField make_field_constant_if_possible(GField field)
Definition: field.cc:508
Vector< GVArray > evaluate_fields(ResourceScope &scope, Span< GFieldRef > fields_to_evaluate, IndexMask mask, const FieldContext &context, Span< GVMutableArray > dst_varrays={})
Definition: field.cc:278
Field< bool > invert_boolean_field(const Field< bool > &field)
Definition: field.cc:521
void evaluate_constant_field(const GField &field, void *r_value)
Definition: field.cc:494
static constexpr bool is_field_v
Definition: FN_field.hh:198
uint64_t get_default_hash(const T &v)
Definition: BLI_hash.hh:218
uint64_t get_default_hash_2(const T1 &v1, const T2 &v2)
Definition: BLI_hash.hh:223
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
__int64 int64_t
Definition: stdint.h:89
unsigned __int64 uint64_t
Definition: stdint.h:90
VectorSet< const FieldInput * > nodes
Definition: FN_field.hh:296
VectorSet< std::reference_wrapper< const FieldInput > > deduplicated_nodes
Definition: FN_field.hh:301
Field< T > as_field() const
Definition: FN_field.hh:552
ValueOrField(Field< T > field)
Definition: FN_field.hh:543