31using bke::bNodeTreeZone;
32using bke::bNodeTreeZones;
38 this->value.destruct();
43 const std::shared_ptr<const fn::FieldInputs> &field_input_nodes = field.node().field_inputs();
47 if (field_input_nodes) {
48 field_inputs.
extend(field_input_nodes->deduplicated_nodes.begin(),
49 field_input_nodes->deduplicated_nodes.end());
54 const int index_a = int(a.category());
55 const int index_b = int(b.category());
56 if (index_a == index_b) {
57 return a.socket_inspection_name().size() < b.socket_inspection_name().size();
59 return index_a < index_b;
62 for (
const FieldInput &field_input : field_inputs) {
63 this->input_tooltips.append(field_input.socket_inspection_name());
69 this->name = geometry_set.
name;
90 this->attributes.append({attribute_id, meta_data.domain, meta_data.data_type});
95 this->component_types.append(component->type());
96 switch (component->type()) {
99 MeshInfo &info = this->mesh_info.emplace();
107 CurveInfo &info = this->curve_info.emplace();
115 PointCloudInfo &info = this->pointcloud_info.emplace();
120 const auto &instances_component = *
static_cast<const bke::InstancesComponent *
>(component);
121 InstancesInfo &info = this->instances_info.emplace();
126 const auto &edit_component = *
static_cast<const bke::GeometryComponentEditData *
>(
128 if (!this->edit_data_info) {
129 this->edit_data_info.emplace(EditDataInfo());
131 EditDataInfo &info = *this->edit_data_info;
132 if (
const bke::CurvesEditHints *curve_edit_hints = edit_component.curves_edit_hints_.get())
134 info.has_deform_matrices = curve_edit_hints->deform_mats.has_value();
135 info.has_deformed_positions = curve_edit_hints->positions().has_value();
137 if (
const bke::GizmoEditHints *gizmo_edit_hints = edit_component.gizmo_edit_hints_.get()) {
138 info.gizmo_transforms_num = gizmo_edit_hints->gizmo_transforms.size();
143 const auto &volume_component = *
static_cast<const bke::VolumeComponent *
>(component);
144 if (
const Volume *volume = volume_component.get()) {
145 VolumeInfo &info = this->volume_info.emplace();
151 const auto &grease_pencil_component = *
static_cast<const bke::GreasePencilComponent *
>(
153 if (
const GreasePencil *grease_pencil = grease_pencil_component.get()) {
154 GreasePencilInfo &info = this->grease_pencil_info.emplace(GreasePencilInfo());
155 info.layers_num = grease_pencil->layers().size();
164struct GridIsEmptyOp {
165 const openvdb::GridBase &base_grid;
170 result =
static_cast<const GridType &
>(base_grid).empty();
176GeometryInfoLog::GeometryInfoLog(
const bke::GVolumeGrid &grid)
178 GridInfo &info = this->grid_info.emplace();
180 bke::VolumeTreeAccessToken token;
181 const openvdb::GridBase &vdb_grid = grid->grid(token);
184 GridIsEmptyOp is_empty_op{vdb_grid};
185 if (BKE_volume_grid_type_operation(grid_type, is_empty_op)) {
198GeoModifierLog::GeoModifierLog() =
default;
199GeoModifierLog::~GeoModifierLog() =
default;
201GeoTreeLogger::GeoTreeLogger() =
default;
202GeoTreeLogger::~GeoTreeLogger() =
default;
204GeoNodeLog::GeoNodeLog() =
default;
205GeoNodeLog::~GeoNodeLog() =
default;
208 : modifier_log_(modifier_log), tree_loggers_(std::move(tree_loggers))
212 children_hashes_.add(
hash);
221 const CPPType &type = *value.type();
227 {node.
identifier, socket.index(), std::move(value_log)});
230 auto log_generic_value = [&](
const CPPType &type,
const void *value) {
232 type.copy_construct(value, buffer);
248 const bke::GVolumeGrid grid = value_variant.
extract<bke::GVolumeGrid>();
255 log_generic_value(*value.type(), value.get());
259 log_generic_value(type, value.get());
266 log->geometry = std::move(geometry);
267 log->geometry.ensure_owns_direct_data();
274 switch (propagation) {
290 if (reduced_node_warnings_) {
298 if (
const bNode *node =
tree->node_by_id(warning.node_id)) {
302 this->nodes.lookup_or_add_default(warning.node_id).warnings.add(warning.warning);
310 if (child_log.tree_loggers_.is_empty()) {
315 const std::optional<int32_t> &parent_node_id = child_log.tree_loggers_[0]->parent_node_id;
316 if (
tree && parent_node_id) {
317 if (
const bNode *node =
tree->node_by_id(*parent_node_id)) {
319 if (node->is_group() && node->id) {
320 child_tree =
reinterpret_cast<const bNodeTree *
>(node->id);
328 if (parent_node_id.has_value()) {
329 this->nodes.lookup_or_add_default(*parent_node_id)
339 reduced_node_warnings_ =
true;
344 if (reduced_execution_times_) {
349 const std::chrono::nanoseconds duration = timings.end - timings.start;
350 this->nodes.lookup_or_add_default_as(timings.node_id).execution_time += duration;
354 reduced_execution_times_ =
true;
359 if (reduced_socket_values_) {
364 this->nodes.lookup_or_add_as(value_log_data.node_id)
365 .input_values_.add(value_log_data.socket_index, value_log_data.value.get());
368 this->nodes.lookup_or_add_as(value_log_data.node_id)
369 .output_values_.add(value_log_data.socket_index, value_log_data.value.get());
372 reduced_socket_values_ =
true;
377 if (reduced_viewer_node_logs_) {
382 this->
viewer_node_logs.add(viewer_log.node_id, viewer_log.viewer_log.get());
385 reduced_viewer_node_logs_ =
true;
390 if (reduced_existing_attributes_) {
395 auto handle_value_log = [&](
const ValueLog &value_log) {
405 for (
const GeoNodeLog &node_log : this->nodes.values()) {
406 for (
const ValueLog *value_log : node_log.input_values_.values()) {
407 handle_value_log(*value_log);
409 for (
const ValueLog *value_log : node_log.output_values_.values()) {
410 handle_value_log(*value_log);
413 reduced_existing_attributes_ =
true;
418 if (reduced_used_named_attributes_) {
422 auto add_attribute = [&](
const int32_t node_id,
425 this->nodes.lookup_or_add_default(node_id).used_named_attributes.lookup_or_add(attribute_name,
432 add_attribute(item.node_id, item.attribute_name, item.usage);
437 if (child_log.tree_loggers_.is_empty()) {
441 if (
const std::optional<int32_t> &parent_node_id = child_log.tree_loggers_[0]->parent_node_id)
444 add_attribute(*parent_node_id, item.key, item.value);
448 reduced_used_named_attributes_ =
true;
453 if (reduced_debug_messages_) {
458 this->nodes.lookup_or_add_as(debug_message.node_id)
459 .debug_messages.append(debug_message.message);
462 reduced_debug_messages_ =
true;
467 if (reduced_evaluated_gizmo_nodes_) {
472 tree_logger->evaluated_gizmo_nodes)
488 if (query_socket.is_multi_input()) {
495 sockets_to_check.
push(&query_socket);
496 added_sockets.
add(&query_socket);
498 while (!sockets_to_check.
is_empty()) {
500 const bNode &node = socket.owner_node();
501 if (
GeoNodeLog *node_log = this->nodes.lookup_ptr(node.identifier)) {
502 ValueLog *value_log = socket.is_input() ?
503 node_log->input_values_.lookup_default(socket.index(),
nullptr) :
504 node_log->output_values_.lookup_default(socket.index(),
nullptr);
505 if (value_log !=
nullptr) {
510 if (socket.is_input()) {
514 if (added_sockets.
add(&from_socket)) {
515 sockets_to_check.
push(&from_socket);
520 if (node.is_reroute()) {
521 const bNodeSocket &input_socket = node.input_socket(0);
522 if (added_sockets.
add(&input_socket)) {
523 sockets_to_check.
push(&input_socket);
528 if (added_sockets.
add(&from_socket)) {
529 sockets_to_check.
push(&from_socket);
533 else if (node.is_muted()) {
534 if (
const bNodeSocket *input_socket = socket.internal_link_input()) {
535 if (added_sockets.
add(input_socket)) {
536 sockets_to_check.
push(input_socket);
541 if (added_sockets.
add(&from_socket)) {
542 sockets_to_check.
push(&from_socket);
557 const void *src_value = value_log.
value.
get();
563 if (!conversions.
is_convertible(src_type, dst_type) && src_type != dst_type) {
573 LocalData &local_data = data_per_thread_.
local();
575 local_data.tree_logger_by_context;
577 compute_context.
hash());
578 if (tree_logger_ptr) {
579 return *tree_logger_ptr;
583 tree_logger.allocator = &local_data.allocator;
585 if (parent_compute_context !=
nullptr) {
586 tree_logger.parent_hash = parent_compute_context->
hash();
593 tree_logger.parent_node_id.emplace(typed_compute_context->node_id());
598 tree_logger.parent_node_id.emplace(typed_compute_context->output_node_id());
604 tree_logger.parent_node_id.emplace(typed_compute_context->output_node_id());
609 tree_logger.parent_node_id.emplace(typed_compute_context->output_node_id());
616 GeoTreeLog &reduced_tree_log = *tree_logs_.lookup_or_add_cb(compute_context_hash, [&]() {
618 for (LocalData &local_data : data_per_thread_) {
620 compute_context_hash);
621 if (tree_log !=
nullptr) {
622 tree_logs.
append(tree_log->get());
625 return std::make_unique<GeoTreeLog>(
this, std::move(tree_logs));
627 return reduced_tree_log;
635 switch (zone.output_node->type) {
642 zone.output_node->storage);
644 storage.inspection_index);
649 zone.output_node->storage);
651 *zone.output_node, storage.inspection_index);
655 r_hash_by_zone.
add_new(&zone, compute_context_builder.
hash());
659 compute_context_builder.
pop();
671 if (tree_zones ==
nullptr) {
675 hash_by_zone.
add_new(
nullptr, compute_context_builder.
hash());
695 std::optional<ed::space_node::ObjectAndModifier> object_and_modifier =
697 if (!object_and_modifier) {
700 GeoModifierLog *modifier_log = object_and_modifier->nmd->runtime->eval_log.get();
701 if (modifier_log ==
nullptr) {
706 snode, object_and_modifier->nmd->modifier.name);
708 for (
const auto item : hash_by_zone.
items()) {
710 log_by_zone.
add(item.key, &tree_log);
725 for (
const auto item : hash_by_zone.items()) {
727 log_by_zone.
add(item.key, &tree_log);
738 const std::optional<ed::viewer_path::ViewerPathForGeometryNodesViewer> parsed_path =
740 if (!parsed_path.has_value()) {
743 const Object *
object = parsed_path->object;
746 if (md->name == parsed_path->modifier_name) {
752 if (nmd ==
nullptr) {
773 parsed_path->viewer_node_id,
nullptr);
Low-level operations for curves.
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT
#define GEO_NODE_SIMULATION_OUTPUT
#define GEO_NODE_REPEAT_OUTPUT
int BKE_volume_num_grids(const Volume *volume)
#define BLI_assert_unreachable()
#define LISTBASE_FOREACH(type, var, list)
@ NODE_WARNING_PROPAGATION_NONE
@ NODE_WARNING_PROPAGATION_ONLY_ERRORS_AND_WARNINGS
@ NODE_WARNING_PROPAGATION_ONLY_ERRORS
@ NODE_WARNING_PROPAGATION_ALL
SpaceNodeGeometryNodesType
@ SNODE_GEOMETRY_MODIFIER
void destruct(void *ptr) const
const ComputeContextHash hash() const
void push(Args &&...args)
const ComputeContext * parent() const
const ComputeContextHash & hash() const
const CPPType * type() const
destruct_ptr< T > construct(Args &&...args)
void * allocate(const int64_t size, const int64_t alignment)
Value & lookup_or_add_default(const Key &key)
bool add(const Key &key, const Value &value)
void add_new(const Key &key, const Value &value)
ItemIterator items() const
constexpr bool contains(const T &value) const
void push(const T &value)
void append(const T &value)
void extend(Span< T > array)
void convert_to_uninitialized(const CPPType &from_type, const CPPType &to_type, const void *from_value, void *to_value) const
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
int attribute_domain_size(AttrDomain domain) const
bool is_context_dependent_field() const
bool is_volume_grid() const
GPointer get_single_ptr() const
Vector< bNodeTreeZone * > root_zones
FieldInfoLog(const GField &field)
GeoTreeLog & get_tree_log(const ComputeContextHash &compute_context_hash)
GeoTreeLogger & get_local_tree_logger(const ComputeContext &compute_context)
static Map< const bke::bNodeTreeZone *, GeoTreeLog * > get_tree_log_by_zone_for_node_editor(const SpaceNode &snode)
static const ViewerNodeLog * find_viewer_node_log_for_path(const ViewerPath &viewer_path)
static Map< const bke::bNodeTreeZone *, ComputeContextHash > get_context_hash_by_zone_for_node_editor(const SpaceNode &snode, StringRefNull modifier_name)
Vector< const GeometryAttributeInfo * > existing_attributes
void ensure_evaluated_gizmo_nodes()
void ensure_used_named_attributes()
VectorSet< NodeWarning > all_warnings
Set< int > evaluated_gizmo_nodes
void ensure_existing_attributes()
void ensure_socket_values()
void ensure_node_warnings(const bNodeTree *tree)
bool try_convert_primitive_socket_value(const GenericValueLog &value_log, const CPPType &dst_type, void *dst)
std::chrono::nanoseconds execution_time
void ensure_execution_times()
void ensure_viewer_node_logs()
Map< int32_t, ViewerNodeLog *, 0 > viewer_node_logs
Map< StringRefNull, NamedAttributeUsage > used_named_attributes
void ensure_debug_messages()
ValueLog * find_socket_value_log(const bNodeSocket &query_socket)
linear_allocator::ChunkedList< ViewerNodeLogWithNode > viewer_node_logs
void log_viewer_node(const bNode &viewer_node, bke::GeometrySet geometry)
LinearAllocator * allocator
linear_allocator::ChunkedList< SocketValueLog, 16 > input_socket_values
void log_value(const bNode &node, const bNodeSocket &socket, GPointer value)
linear_allocator::ChunkedList< SocketValueLog, 16 > output_socket_values
Vector< ComputeContextHash > children_hashes
local_group_size(16, 16) .push_constant(Type b
static const char * modifier_name[LS_MODIFIER_NUM]
ccl_device_inline float3 log(float3 v)
VolumeGridType get_type(const VolumeGridData &grid)
bool attribute_name_is_anonymous(const StringRef name)
const DataTypeConversions & get_implicit_type_conversions()
Span< int > all_zone_output_node_types()
const GeoOperatorLog & node_group_operator_static_eval_log()
bool push_compute_context_for_tree_path(const SpaceNode &snode, ComputeContextBuilder &compute_context_builder)
std::optional< ObjectAndModifier > get_modifier_for_node_editor(const SpaceNode &snode)
bool add_compute_context_for_viewer_path_elem(const ViewerPathElem &elem, ComputeContextBuilder &compute_context_builder)
std::optional< ViewerPathForGeometryNodesViewer > parse_geometry_nodes_viewer(const ViewerPath &viewer_path)
int node_warning_type_icon(const NodeWarningType type)
int node_warning_type_severity(const NodeWarningType type)
static bool warning_is_propagated(const NodeWarningPropagation propagation, const NodeWarningType warning_type)
static void find_tree_zone_hash_recursive(const bNodeTreeZone &zone, ComputeContextBuilder &compute_context_builder, Map< const bNodeTreeZone *, ComputeContextHash > &r_hash_by_zone)
std::unique_ptr< T, DestructValueAtAddress< T > > destruct_ptr
NodesModifierRuntimeHandle * runtime
struct bNodeTree * edittree
struct bNodeTree * geometry_nodes_tool_tree
void attribute_foreach(Span< GeometryComponent::Type > component_types, bool include_instances, AttributeForeachCallback callback) const