Blender  V3.3
NOD_geometry_nodes_eval_log.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
20 #include "BLI_function_ref.hh"
21 #include "BLI_generic_pointer.hh"
22 #include "BLI_linear_allocator.hh"
23 #include "BLI_map.hh"
24 
25 #include "BKE_geometry_set.hh"
26 
27 #include "NOD_derived_node_tree.hh"
28 
29 #include "FN_field.hh"
30 
31 #include <chrono>
32 
33 struct SpaceNode;
34 struct SpaceSpreadsheet;
35 
37 
39 class ValueLog {
40  public:
41  virtual ~ValueLog() = default;
42 };
43 
45 class GenericValueLog : public ValueLog {
46  private:
47  GMutablePointer data_;
48 
49  public:
51  {
52  }
53 
55  {
56  data_.destruct();
57  }
58 
59  GPointer value() const
60  {
61  return data_;
62  }
63 };
64 
65 class GFieldValueLog : public ValueLog {
66  private:
67  fn::GField field_;
68  const CPPType &type_;
69  Vector<std::string> input_tooltips_;
70 
71  public:
72  GFieldValueLog(fn::GField field, bool log_full_field);
73 
74  const fn::GField &field() const
75  {
76  return field_;
77  }
78 
80  {
81  return input_tooltips_;
82  }
83 
84  const CPPType &type() const
85  {
86  return type_;
87  }
88 };
89 
91  std::string name;
93  std::optional<eAttrDomain> domain;
94  std::optional<eCustomDataType> data_type;
95 };
96 
99 class GeometryValueLog : public ValueLog {
100  private:
101  Vector<GeometryAttributeInfo> attributes_;
102  Vector<GeometryComponentType> component_types_;
103  std::unique_ptr<GeometrySet> full_geometry_;
104 
105  public:
106  struct MeshInfo {
108  };
109  struct CurveInfo {
111  };
112  struct PointCloudInfo {
114  };
115  struct InstancesInfo {
117  };
118  struct EditDataInfo {
121  };
122 
123  std::optional<MeshInfo> mesh_info;
124  std::optional<CurveInfo> curve_info;
125  std::optional<PointCloudInfo> pointcloud_info;
126  std::optional<InstancesInfo> instances_info;
127  std::optional<EditDataInfo> edit_data_info;
128 
129  GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry = false);
130 
132  {
133  return attributes_;
134  }
135 
137  {
138  return component_types_;
139  }
140 
141  const GeometrySet *full_geometry() const
142  {
143  return full_geometry_.get();
144  }
145 };
146 
147 enum class NodeWarningType {
148  Error,
149  Warning,
150  Info,
151 };
152 
153 struct NodeWarning {
155  std::string message;
156 };
157 
161 };
162 
165  std::chrono::microseconds exec_time;
166 };
167 
170  std::string message;
171 };
172 
177 };
178 
179 enum class eNamedAttrUsage {
180  None = 0,
181  Read = 1 << 0,
182  Write = 1 << 1,
183  Remove = 1 << 2,
184 };
186 
188  std::string name;
190 };
191 
195 };
196 
197 class GeoLogger;
198 class ModifierLog;
199 
203  private:
204  /* Back pointer to the owner of this local logger. */
205  GeoLogger *main_logger_;
206  /* Allocator for the many small allocations during logging. This is in a `unique_ptr` so that
207  * ownership can be transferred later on. */
208  std::unique_ptr<LinearAllocator<>> allocator_;
209  Vector<ValueOfSockets> values_;
210  Vector<NodeWithWarning> node_warnings_;
211  Vector<NodeWithExecutionTime> node_exec_times_;
212  Vector<NodeWithDebugMessage> node_debug_messages_;
213  Vector<NodeWithUsedNamedAttribute> used_named_attributes_;
214 
215  friend ModifierLog;
216 
217  public:
218  LocalGeoLogger(GeoLogger &main_logger) : main_logger_(&main_logger)
219  {
220  this->allocator_ = std::make_unique<LinearAllocator<>>();
221  }
222 
223  void log_value_for_sockets(Span<DSocket> sockets, GPointer value);
224  void log_multi_value_socket(DSocket socket, Span<GPointer> values);
225  void log_node_warning(DNode node, NodeWarningType type, std::string message);
226  void log_execution_time(DNode node, std::chrono::microseconds exec_time);
227  void log_used_named_attribute(DNode node, std::string attribute_name, eNamedAttrUsage usage);
232  void log_debug_message(DNode node, std::string message);
233 };
234 
236 class GeoLogger {
237  private:
243  Set<DSocket> log_full_sockets_;
245 
246  /* These are only optional since they don't have a default constructor. */
247  std::unique_ptr<GeometryValueLog> input_geometry_log_;
248  std::unique_ptr<GeometryValueLog> output_geometry_log_;
249 
250  friend LocalGeoLogger;
251  friend ModifierLog;
252 
253  public:
254  GeoLogger(Set<DSocket> log_full_sockets)
255  : log_full_sockets_(std::move(log_full_sockets)),
256  threadlocals_([this]() { return LocalGeoLogger(*this); })
257  {
258  }
259 
260  void log_input_geometry(const GeometrySet &geometry)
261  {
262  input_geometry_log_ = std::make_unique<GeometryValueLog>(geometry);
263  }
264 
265  void log_output_geometry(const GeometrySet &geometry)
266  {
267  output_geometry_log_ = std::make_unique<GeometryValueLog>(geometry);
268  }
269 
271  {
272  return threadlocals_.local();
273  }
274 
275  auto begin()
276  {
277  return threadlocals_.begin();
278  }
279 
280  auto end()
281  {
282  return threadlocals_.end();
283  }
284 };
285 
287 class SocketLog {
288  private:
289  ValueLog *value_ = nullptr;
290 
291  friend ModifierLog;
292 
293  public:
294  const ValueLog *value() const
295  {
296  return value_;
297  }
298 };
299 
301 class NodeLog {
302  private:
303  Vector<SocketLog> input_logs_;
304  Vector<SocketLog> output_logs_;
305  Vector<NodeWarning, 0> warnings_;
306  Vector<std::string, 0> debug_messages_;
307  Vector<UsedNamedAttribute, 0> used_named_attributes_;
308  std::chrono::microseconds exec_time_;
309 
310  friend ModifierLog;
311 
312  public:
313  const SocketLog *lookup_socket_log(eNodeSocketInOut in_out, int index) const;
314  const SocketLog *lookup_socket_log(const bNode &node, const bNodeSocket &socket) const;
315  void execution_time(std::chrono::microseconds exec_time);
316 
318  {
319  return input_logs_;
320  }
321 
323  {
324  return output_logs_;
325  }
326 
328  {
329  return warnings_;
330  }
331 
333  {
334  return debug_messages_;
335  }
336 
338  {
339  return used_named_attributes_;
340  }
341 
342  std::chrono::microseconds execution_time() const
343  {
344  return exec_time_;
345  }
346 
348 };
349 
351 class TreeLog {
352  private:
355 
356  friend ModifierLog;
357 
358  public:
359  const NodeLog *lookup_node_log(StringRef node_name) const;
360  const NodeLog *lookup_node_log(const bNode &node) const;
361  const TreeLog *lookup_child_log(StringRef node_name) const;
362  void foreach_node_log(FunctionRef<void(const NodeLog &)> fn) const;
363 };
364 
366 class ModifierLog {
367  private:
368  LinearAllocator<> allocator_;
369  /* Allocators of the individual loggers. */
370  Vector<std::unique_ptr<LinearAllocator<>>> logger_allocators_;
371  destruct_ptr<TreeLog> root_tree_logs_;
372  Vector<destruct_ptr<ValueLog>> logged_values_;
373 
374  std::unique_ptr<GeometryValueLog> input_geometry_log_;
375  std::unique_ptr<GeometryValueLog> output_geometry_log_;
376 
377  public:
378  ModifierLog(GeoLogger &logger);
379 
380  const TreeLog &root_tree() const
381  {
382  return *root_tree_logs_;
383  }
384 
385  /* Utilities to find logged information for a specific context. */
386  static const ModifierLog *find_root_by_node_editor_context(const SpaceNode &snode);
387  static const TreeLog *find_tree_by_node_editor_context(const SpaceNode &snode);
388  static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode,
389  const bNode &node);
390  static const NodeLog *find_node_by_node_editor_context(const SpaceNode &snode,
391  const StringRef node_name);
392  static const SocketLog *find_socket_by_node_editor_context(const SpaceNode &snode,
393  const bNode &node,
394  const bNodeSocket &socket);
396  const SpaceSpreadsheet &sspreadsheet);
397  void foreach_node_log(FunctionRef<void(const NodeLog &)> fn) const;
398 
399  const GeometryValueLog *input_geometry_log() const;
400  const GeometryValueLog *output_geometry_log() const;
401 
402  private:
403  using LogByTreeContext = Map<const DTreeContext *, TreeLog *>;
404 
405  TreeLog &lookup_or_add_tree_log(LogByTreeContext &log_by_tree_context,
406  const DTreeContext &tree_context);
407  NodeLog &lookup_or_add_node_log(LogByTreeContext &log_by_tree_context, DNode node);
408  SocketLog &lookup_or_add_socket_log(LogByTreeContext &log_by_tree_context, DSocket socket);
409 };
410 
411 } // namespace blender::nodes::geometry_nodes_eval_log
eNodeSocketInOut
_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
GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry=false)
void log_node_warning(DNode node, NodeWarningType type, std::string message)
void log_multi_value_socket(DSocket socket, Span< GPointer > values)
void log_execution_time(DNode node, std::chrono::microseconds exec_time)
void log_used_named_attribute(DNode node, std::string attribute_name, eNamedAttrUsage usage)
void log_value_for_sockets(Span< DSocket > sockets, GPointer value)
static const NodeLog * find_node_by_node_editor_context(const SpaceNode &snode, const bNode &node)
void foreach_node_log(FunctionRef< void(const NodeLog &)> fn) const
static const TreeLog * find_tree_by_node_editor_context(const SpaceNode &snode)
static const NodeLog * find_node_by_spreadsheet_editor_context(const SpaceSpreadsheet &sspreadsheet)
static const SocketLog * find_socket_by_node_editor_context(const SpaceNode &snode, const bNode &node, const bNodeSocket &socket)
static const ModifierLog * find_root_by_node_editor_context(const SpaceNode &snode)
void execution_time(std::chrono::microseconds exec_time)
Vector< const GeometryAttributeInfo * > lookup_available_attributes() const
const SocketLog * lookup_socket_log(eNodeSocketInOut in_out, int index) const
const TreeLog * lookup_child_log(StringRef node_name) const
void foreach_node_log(FunctionRef< void(const NodeLog &)> fn) const
const NodeLog * lookup_node_log(StringRef node_name) const
OperationNode * node
T * data_
Definition: eval_output.h:163
ENUM_OPERATORS(eNamedAttrUsage, eNamedAttrUsage::Remove)
std::unique_ptr< T, DestructValueAtAddress< T > > destruct_ptr