Geometry Nodes: add simulation support #104924

Closed
Hans Goudey wants to merge 211 commits from geometry-nodes-simulation into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 59 additions and 70 deletions
Showing only changes of commit 988241e23e - Show all commits

View File

@ -143,6 +143,8 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
bool has_undefined_nodes_or_sockets = false;
bNode *group_output_node = nullptr;
Vector<bNode *> root_frames;
Vector<bNodeSocket *> interface_inputs;
Vector<bNodeSocket *> interface_outputs;
};
/**
@ -430,6 +432,18 @@ inline blender::Span<const bNode *> bNodeTree::group_input_nodes() const
return this->nodes_by_type("NodeGroupInput");
}
inline blender::Span<const bNodeSocket *> bNodeTree::interface_inputs() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->interface_inputs;
}
inline blender::Span<const bNodeSocket *> bNodeTree::interface_outputs() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));
return this->runtime->interface_outputs;
}
inline blender::Span<const bNodeSocket *> bNodeTree::all_input_sockets() const
{
BLI_assert(blender::bke::node_tree_runtime::topology_cache_is_available(*this));

View File

@ -42,6 +42,13 @@ static void double_checked_lock_with_task_isolation(std::mutex &mutex,
double_checked_lock(mutex, data_is_dirty, [&]() { threading::isolate_task(fn); });
}
static void update_interface_sockets(const bNodeTree &ntree)
{
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
tree_runtime.interface_inputs = ntree.inputs;
tree_runtime.interface_outputs = ntree.outputs;
}
static void update_node_vector(const bNodeTree &ntree)
{
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
@ -429,6 +436,7 @@ static void ensure_topology_cache(const bNodeTree &ntree)
bNodeTreeRuntime &tree_runtime = *ntree.runtime;
double_checked_lock_with_task_isolation(
tree_runtime.topology_cache_mutex, tree_runtime.topology_cache_is_dirty, [&]() {
update_interface_sockets(ntree);
update_node_vector(ntree);
update_link_vector(ntree);
update_socket_vectors_and_owner_node(ntree);

View File

@ -636,6 +636,9 @@ typedef struct bNodeTree {
const bNode *group_output_node() const;
/** Get all input nodes of the node group. */
blender::Span<const bNode *> group_input_nodes() const;
/** Inputs and outputs of the entire node group. */
blender::Span<const bNodeSocket *> interface_inputs() const;
blender::Span<const bNodeSocket *> interface_outputs() const;
#endif
} bNodeTree;

View File

@ -746,20 +746,9 @@ struct GeometryNodesLazyFunctionGraphBuilder {
/**
* All group input nodes are combined into one dummy node in the lazy-function graph.
* If some input has an invalid type, it is ignored in the new graph. In this case null and -1 is
* used in the vectors below.
*/
Vector<const CPPType *> group_input_types_;
Vector<int> group_input_indices_;
lf::DummyNode *group_input_lf_node_;
/**
* The output types or null if an output is invalid. Each group output node gets a separate
* corresponding dummy node in the new graph.
*/
Vector<const CPPType *> group_output_types_;
Vector<int> group_output_indices_;
public:
GeometryNodesLazyFunctionGraphBuilder(const bNodeTree &btree,
GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
@ -776,8 +765,6 @@ struct GeometryNodesLazyFunctionGraphBuilder {
conversions_ = &bke::get_implicit_type_conversions();
this->prepare_node_multi_functions();
this->prepare_group_inputs();
this->prepare_group_outputs();
this->build_group_input_node();
this->handle_nodes();
this->handle_links();
@ -793,50 +780,21 @@ struct GeometryNodesLazyFunctionGraphBuilder {
lf_graph_info_->node_multi_functions = std::make_unique<NodeMultiFunctions>(btree_);
}
void prepare_group_inputs()
{
LISTBASE_FOREACH (const bNodeSocket *, interface_bsocket, &btree_.inputs) {
const CPPType *type = get_socket_cpp_type(*interface_bsocket->typeinfo);
if (type != nullptr) {
const int index = group_input_types_.append_and_get_index(type);
group_input_indices_.append(index);
}
else {
group_input_indices_.append(-1);
}
}
}
void prepare_group_outputs()
{
LISTBASE_FOREACH (const bNodeSocket *, interface_bsocket, &btree_.outputs) {
const CPPType *type = get_socket_cpp_type(*interface_bsocket->typeinfo);
if (type != nullptr) {
const int index = group_output_types_.append_and_get_index(type);
group_output_indices_.append(index);
}
else {
group_output_indices_.append(-1);
}
}
}
void build_group_input_node()
{
Vector<const CPPType *, 16> input_cpp_types;
const Span<const bNodeSocket *> interface_inputs = btree_.interface_inputs();
for (const bNodeSocket *interface_input : interface_inputs) {
input_cpp_types.append(interface_input->typeinfo->geometry_nodes_cpp_type);
}
/* Create a dummy node for the group inputs. */
auto debug_info = std::make_unique<GroupInputDebugInfo>();
group_input_lf_node_ = &lf_graph_->add_dummy({}, group_input_types_, debug_info.get());
group_input_lf_node_ = &lf_graph_->add_dummy({}, input_cpp_types, debug_info.get());
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.inputs.first);
for (const int group_input_index : group_input_indices_) {
BLI_SCOPED_DEFER([&]() { interface_bsocket = interface_bsocket->next; });
if (group_input_index == -1) {
mapping_->group_input_sockets.append(nullptr);
}
else {
mapping_->group_input_sockets.append(&group_input_lf_node_->output(group_input_index));
debug_info->socket_names.append(interface_bsocket->name);
}
for (const int i : interface_inputs.index_range()) {
mapping_->group_input_sockets.append(&group_input_lf_node_->output(i));
debug_info->socket_names.append(interface_inputs[i]->name);
}
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
}
@ -951,13 +909,9 @@ struct GeometryNodesLazyFunctionGraphBuilder {
void handle_group_input_node(const bNode &bnode)
{
for (const int btree_index : group_input_indices_.index_range()) {
const int lf_index = group_input_indices_[btree_index];
if (lf_index == -1) {
continue;
}
const bNodeSocket &bsocket = bnode.output_socket(btree_index);
lf::OutputSocket &lf_socket = group_input_lf_node_->output(lf_index);
for (const int i : btree_.interface_inputs().index_range()) {
const bNodeSocket &bsocket = bnode.output_socket(i);
lf::OutputSocket &lf_socket = group_input_lf_node_->output(i);
output_socket_map_.add_new(&bsocket, &lf_socket);
mapping_->dummy_socket_map.add_new(&bsocket, &lf_socket);
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
@ -966,23 +920,23 @@ struct GeometryNodesLazyFunctionGraphBuilder {
void handle_group_output_node(const bNode &bnode)
{
Vector<const CPPType *, 16> output_cpp_types;
const Span<const bNodeSocket *> interface_outputs = btree_.interface_outputs();
for (const bNodeSocket *interface_input : interface_outputs) {
output_cpp_types.append(interface_input->typeinfo->geometry_nodes_cpp_type);
}
auto debug_info = std::make_unique<GroupOutputDebugInfo>();
lf::DummyNode &group_output_lf_node = lf_graph_->add_dummy(
group_output_types_, {}, debug_info.get());
output_cpp_types, {}, debug_info.get());
const bNodeSocket *interface_bsocket = static_cast<bNodeSocket *>(btree_.outputs.first);
for (const int btree_index : group_output_indices_.index_range()) {
BLI_SCOPED_DEFER([&]() { interface_bsocket = interface_bsocket->next; });
const int lf_index = group_output_indices_[btree_index];
if (lf_index == -1) {
continue;
}
const bNodeSocket &bsocket = bnode.input_socket(btree_index);
lf::InputSocket &lf_socket = group_output_lf_node.input(lf_index);
for (const int i : interface_outputs.index_range()) {
const bNodeSocket &bsocket = bnode.input_socket(i);
lf::InputSocket &lf_socket = group_output_lf_node.input(i);
input_socket_map_.add(&bsocket, &lf_socket);
mapping_->dummy_socket_map.add(&bsocket, &lf_socket);
mapping_->bsockets_by_lf_socket_map.add(&lf_socket, &bsocket);
debug_info->socket_names.append(interface_bsocket->name);
debug_info->socket_names.append(interface_outputs[i]->name);
}
lf_graph_info_->dummy_debug_infos_.append(std::move(debug_info));
@ -1317,6 +1271,16 @@ const GeometryNodesLazyFunctionGraphInfo *ensure_geometry_nodes_lazy_function_gr
return nullptr;
}
}
for (const bNodeSocket *interface_bsocket : btree.interface_inputs()) {
if (interface_bsocket->typeinfo->geometry_nodes_cpp_type == nullptr) {
return nullptr;
}
}
for (const bNodeSocket *interface_bsocket : btree.interface_outputs()) {
if (interface_bsocket->typeinfo->geometry_nodes_cpp_type == nullptr) {
return nullptr;
}
}
std::unique_ptr<GeometryNodesLazyFunctionGraphInfo> &lf_graph_info_ptr =
btree.runtime->geometry_nodes_lazy_function_graph_info;