Depsgraph: Use C++ Stack class

Use `blender::Stack` instead of `BLI_Stack`. Theoretically this can
improve performance because it makes use of inlining to remove function
call overhead and give the compiler more information. I observed a build
time improvement of about 4%, from 1156 to 1113 ms with 30k cube objects.
Notably, now `deg_graph_flush_visibility_flags` doesn't call any
non-inlined functions.

Pull Request: https://projects.blender.org/blender/blender/pulls/137355
This commit is contained in:
Hans Goudey
2025-04-11 19:55:17 +02:00
committed by Hans Goudey
parent 9d57b947d9
commit 0ee5e6ded7
2 changed files with 15 additions and 22 deletions

View File

@@ -12,7 +12,7 @@
#include <cstdio>
#include <cstdlib>
#include "BLI_stack.h"
#include "BLI_stack.hh"
#include "intern/node/deg_node.hh"
#include "intern/node/deg_node_component.hh"
@@ -41,20 +41,15 @@ struct StackEntry {
};
struct CyclesSolverState {
CyclesSolverState(Depsgraph *graph)
: graph(graph), traversal_stack(BLI_stack_new(sizeof(StackEntry), "DEG detect cycles stack"))
{
/* pass */
}
CyclesSolverState(Depsgraph *graph) : graph(graph) {}
~CyclesSolverState()
{
BLI_stack_free(traversal_stack);
if (num_cycles != 0) {
printf("Detected %d dependency cycles\n", num_cycles);
}
}
Depsgraph *graph;
BLI_Stack *traversal_stack;
Stack<StackEntry> traversal_stack;
int num_cycles = 0;
};
@@ -84,7 +79,7 @@ void schedule_node_to_stack(CyclesSolverState *state, OperationNode *node)
entry.node = node;
entry.from = nullptr;
entry.via_relation = nullptr;
BLI_stack_push(state->traversal_stack, &entry);
state->traversal_stack.push(entry);
set_node_visited_state(node, NODE_IN_STACK);
}
@@ -153,9 +148,9 @@ Relation *select_relation_to_murder(Relation *relation, StackEntry *cycle_start_
/* Solve cycles with all nodes which are scheduled for traversal. */
void solve_cycles(CyclesSolverState *state)
{
BLI_Stack *traversal_stack = state->traversal_stack;
while (!BLI_stack_is_empty(traversal_stack)) {
StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
Stack<StackEntry> &traversal_stack = state->traversal_stack;
while (!traversal_stack.is_empty()) {
StackEntry *entry = &traversal_stack.peek();
OperationNode *node = entry->node;
bool all_child_traversed = true;
const int num_visited = get_node_num_visited_children(node);
@@ -184,7 +179,7 @@ void solve_cycles(CyclesSolverState *state)
new_entry.node = to;
new_entry.from = entry;
new_entry.via_relation = rel;
BLI_stack_push(traversal_stack, &new_entry);
traversal_stack.push(new_entry);
set_node_visited_state(node, NODE_IN_STACK);
all_child_traversed = false;
set_node_num_visited_children(node, i);
@@ -194,7 +189,7 @@ void solve_cycles(CyclesSolverState *state)
}
if (all_child_traversed) {
set_node_visited_state(node, NODE_VISITED);
BLI_stack_discard(traversal_stack);
traversal_stack.pop();
}
}
}

View File

@@ -14,7 +14,7 @@
#include "BLI_assert.h"
#include "BLI_listbase.h"
#include "BLI_stack.h"
#include "BLI_stack.hh"
#include "DEG_depsgraph.hh"
@@ -122,7 +122,7 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph)
}
}
BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack");
Stack<OperationNode *> stack;
for (OperationNode *op_node : graph->operations) {
op_node->custom_flags = 0;
@@ -133,14 +133,13 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph)
}
}
if (op_node->num_links_pending == 0) {
BLI_stack_push(stack, &op_node);
stack.push(op_node);
op_node->custom_flags |= DEG_NODE_VISITED;
}
}
while (!BLI_stack_is_empty(stack)) {
OperationNode *op_node;
BLI_stack_pop(stack, &op_node);
while (!stack.is_empty()) {
OperationNode *op_node = stack.pop();
/* Flush flags to parents. */
for (Relation *rel : op_node->inlinks) {
@@ -213,13 +212,12 @@ void deg_graph_flush_visibility_flags(Depsgraph *graph)
--op_from->num_links_pending;
}
if ((op_from->num_links_pending == 0) && (op_from->custom_flags & DEG_NODE_VISITED) == 0) {
BLI_stack_push(stack, &op_from);
stack.push(op_from);
op_from->custom_flags |= DEG_NODE_VISITED;
}
}
}
}
BLI_stack_free(stack);
graph->need_update_nodes_visibility = false;
}