Geometry Nodes: visualize evaluated nodes #107780

Open
Jacques Lucke wants to merge 1 commits from JacquesLucke/blender:show-evaluated-nodes into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 78 additions and 13 deletions

View File

@ -2182,6 +2182,12 @@ static void node_draw_basis(const bContext &C,
UI_GetThemeColorBlend4f(TH_NODE, color_id, 0.4f, color_header);
}
if (tree_draw_ctx.geo_tree_log &&
tree_draw_ctx.geo_tree_log->evaluated_node_ids.contains(node.identifier))
{
copy_v4_fl4(color_header, 0.8f, 0.4f, 0.2f, 1.0f);
}
UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
UI_draw_roundbox_4fv(&rect, true, BASIS_RAD, color_header);
}
@ -2518,6 +2524,12 @@ static void node_draw_hidden(const bContext &C,
color[3] -= 0.2f;
}
if (tree_draw_ctx.geo_tree_log &&
tree_draw_ctx.geo_tree_log->evaluated_node_ids.contains(node.identifier))
{
copy_v4_fl4(color, 0.8f, 0.4f, 0.2f, 1.0f);
}
UI_draw_roundbox_4fv(&rct, true, hiddenrad, color);
}
@ -3368,6 +3380,7 @@ static void draw_nodetree(const bContext &C,
if (tree_draw_ctx.geo_tree_log != nullptr) {
tree_draw_ctx.geo_tree_log->ensure_node_warnings();
tree_draw_ctx.geo_tree_log->ensure_node_run_time();
tree_draw_ctx.geo_tree_log->ensure_evaluated_node_ids();
}
const WorkSpace *workspace = CTX_wm_workspace(&C);
tree_draw_ctx.active_geometry_nodes_viewer = viewer_path::find_geometry_nodes_viewer(

View File

@ -208,6 +208,8 @@ class GeoTreeLogger {
Vector<ViewerNodeLogWithNode, 0> viewer_node_logs;
Vector<AttributeUsageWithNode, 0> used_named_attributes;
Vector<DebugMessage, 0> debug_messages;
/** Might contain duplicates. */
Vector<int32_t> evaluated_node_ids;
GeoTreeLogger();
~GeoTreeLogger();
@ -266,6 +268,7 @@ class GeoTreeLog {
bool reduced_existing_attributes_ = false;
bool reduced_used_named_attributes_ = false;
bool reduced_debug_messages_ = false;
bool reduced_evaluated_node_ids_ = false;
public:
Map<int32_t, GeoNodeLog> nodes;
@ -274,6 +277,7 @@ class GeoTreeLog {
std::chrono::nanoseconds run_time_sum{0};
Vector<const GeometryAttributeInfo *> existing_attributes;
Map<StringRefNull, NamedAttributeUsage> used_named_attributes;
Set<int32_t> evaluated_node_ids;
GeoTreeLog(GeoModifierLog *modifier_log, Vector<GeoTreeLogger *> tree_loggers);
~GeoTreeLog();
@ -285,6 +289,7 @@ class GeoTreeLog {
void ensure_existing_attributes();
void ensure_used_named_attributes();
void ensure_debug_messages();
void ensure_evaluated_node_ids();
ValueLog *find_socket_value_log(const bNodeSocket &query_socket);
};

View File

@ -55,9 +55,15 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
void execute_impl(lf::Params &params, const lf::Context &context) const final
{
const GeoNodesLFUserData &user_data = *static_cast<const GeoNodesLFUserData *>(
context.user_data);
const auto &user_data = *static_cast<const GeoNodesLFUserData *>(context.user_data);
const auto &local_user_data = *static_cast<const GeoNodesLFLocalUserData *>(
context.local_user_data);
const GeoNodesModifierData &modifier_data = *user_data.modifier_data;
if (local_user_data.tree_logger) {
local_user_data.tree_logger->evaluated_node_ids.append(node_.identifier);
}
if (modifier_data.current_simulation_state == nullptr) {
params.set_default_remaining_outputs();
return;

View File

@ -407,11 +407,18 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
void execute_impl(lf::Params &params, const lf::Context &context) const final
{
GeoNodesLFUserData &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
auto &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
auto &local_user_data = *static_cast<GeoNodesLFLocalUserData *>(context.local_user_data);
GeoNodesModifierData &modifier_data = *user_data.modifier_data;
EvalData &eval_data = *static_cast<EvalData *>(context.storage);
BLI_SCOPED_DEFER([&]() { eval_data.is_first_evaluation = false; });
if (eval_data.is_first_evaluation) {
if (local_user_data.tree_logger) {
local_user_data.tree_logger->evaluated_node_ids.append(node_.identifier);
}
}
const bke::sim::SimulationZoneID zone_id = get_simulation_zone_id(*user_data.compute_context,
node_.identifier);

View File

@ -146,10 +146,11 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
class LazyFunctionForSwitchNode : public LazyFunction {
private:
const bNode &node_;
bool can_be_field_ = false;
public:
LazyFunctionForSwitchNode(const bNode &node)
LazyFunctionForSwitchNode(const bNode &node) : node_(node)
{
const NodeSwitch &storage = node_storage(node);
const eNodeSocketDatatype data_type = eNodeSocketDatatype(storage.input_type);
@ -171,8 +172,13 @@ class LazyFunctionForSwitchNode : public LazyFunction {
outputs_.append_as("Value", cpp_type);
}
void execute_impl(lf::Params &params, const lf::Context & /*context*/) const override
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
auto &local_user_data = *static_cast<GeoNodesLFLocalUserData *>(context.local_user_data);
if (local_user_data.tree_logger) {
local_user_data.tree_logger->evaluated_node_ids.append(node_.identifier);
}
const ValueOrField<bool> condition = params.get_input<ValueOrField<bool>>(0);
if (condition.is_field() && can_be_field_) {
Field<bool> condition_field = condition.as_field();

View File

@ -303,6 +303,7 @@ class LazyFunctionForGeometryNode : public LazyFunction {
if (local_user_data.tree_logger) {
local_user_data.tree_logger->node_execution_times.append(
{node_.identifier, start_time, end_time});
local_user_data.tree_logger->evaluated_node_ids.append(node_.identifier);
}
}
@ -649,6 +650,7 @@ class LazyFunctionForMultiFunctionConversion : public LazyFunction {
*/
class LazyFunctionForMultiFunctionNode : public LazyFunction {
private:
const bNode &node_;
const NodeMultiFunctions::Item fn_item_;
Vector<const ValueOrFieldCPPType *> input_types_;
Vector<const ValueOrFieldCPPType *> output_types_;
@ -657,7 +659,7 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
LazyFunctionForMultiFunctionNode(const bNode &node,
NodeMultiFunctions::Item fn_item,
MutableSpan<int> r_lf_index_by_bsocket)
: fn_item_(std::move(fn_item))
: node_(node), fn_item_(std::move(fn_item))
{
BLI_assert(fn_item_.fn != nullptr);
debug_name_ = node.name;
@ -670,7 +672,7 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
}
}
void execute_impl(lf::Params &params, const lf::Context & /*context*/) const override
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
Vector<const void *> input_values(inputs_.size());
Vector<void *> output_values(outputs_.size());
@ -685,6 +687,11 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
for (const int i : outputs_.index_range()) {
params.output_set(i);
}
auto &local_user_data = *static_cast<GeoNodesLFLocalUserData *>(context.local_user_data);
if (local_user_data.tree_logger) {
local_user_data.tree_logger->evaluated_node_ids.append(node_.identifier);
}
}
};
@ -799,6 +806,7 @@ class LazyFunctionForViewerNode : public LazyFunction {
}
local_user_data.tree_logger->log_viewer_node(bnode_, std::move(geometry));
local_user_data.tree_logger->evaluated_node_ids.append(bnode_.identifier);
}
};
@ -947,8 +955,8 @@ class LazyFunctionForGroupNode : public LazyFunction {
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
GeoNodesLFUserData *user_data = dynamic_cast<GeoNodesLFUserData *>(context.user_data);
BLI_assert(user_data != nullptr);
auto &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
auto &local_user_data = *static_cast<GeoNodesLFLocalUserData *>(context.local_user_data);
if (has_many_nodes_) {
/* If the called node group has many nodes, it's likely that executing it takes a while even
@ -958,15 +966,22 @@ class LazyFunctionForGroupNode : public LazyFunction {
Storage *storage = static_cast<Storage *>(context.storage);
/* Only log that the node is executed once. */
if (!storage->context_hash_cache.has_value()) {
if (local_user_data.tree_logger) {
local_user_data.tree_logger->evaluated_node_ids.append(group_node_.identifier);
}
}
/* The compute context changes when entering a node group. */
bke::NodeGroupComputeContext compute_context{
user_data->compute_context, group_node_.identifier, storage->context_hash_cache};
user_data.compute_context, group_node_.identifier, storage->context_hash_cache};
storage->context_hash_cache = compute_context.hash();
GeoNodesLFUserData group_user_data = *user_data;
GeoNodesLFUserData group_user_data = user_data;
group_user_data.compute_context = &compute_context;
if (user_data->modifier_data->socket_log_contexts) {
group_user_data.log_socket_values = user_data->modifier_data->socket_log_contexts->contains(
if (user_data.modifier_data->socket_log_contexts) {
group_user_data.log_socket_values = user_data.modifier_data->socket_log_contexts->contains(
compute_context.hash());
}

View File

@ -352,6 +352,19 @@ void GeoTreeLog::ensure_debug_messages()
reduced_debug_messages_ = true;
}
void GeoTreeLog::ensure_evaluated_node_ids()
{
if (reduced_evaluated_node_ids_) {
return;
}
for (GeoTreeLogger *tree_logger : tree_loggers_) {
for (const int32_t node_id : tree_logger->evaluated_node_ids) {
this->evaluated_node_ids.add(node_id);
}
}
reduced_evaluated_node_ids_ = true;
}
ValueLog *GeoTreeLog::find_socket_value_log(const bNodeSocket &query_socket)
{
/**