Files
test2/source/blender/blenkernel/BKE_node_tree_reference_lifetimes.hh
Jacques Lucke 8ec9c62d3e Geometry Nodes: add Closures and Bundles behind experimental feature flag
This implements bundles and closures which are described in more detail in this
blog post: https://code.blender.org/2024/11/geometry-nodes-workshop-october-2024/

tl;dr:
* Bundles are containers that allow storing multiple socket values in a single
  value. Each value in the bundle is identified by a name. Bundles can be
  nested.
* Closures are functions that are created with the Closure Zone and can be
  evaluated with the Evaluate Closure node.

To use the patch, the `Bundle and Closure Nodes` experimental feature has to be
enabled. This is necessary, because these features are not fully done yet and
still need iterations to improve the workflow before they can be officially
released. These iterations are easier to do in `main` than in a separate branch
though. That's because this patch is quite large and somewhat prone to merge
conflicts. Also other work we want to do, depends on this.

This adds the following new nodes:
* Combine Bundle: can pack multiple values into one.
* Separate Bundle: extracts values from a bundle.
* Closure Zone: outputs a closure zone for use in the `Evaluate Closure` node.
* Evaluate Closure: evaluates the passed in closure.

Things that will be added soon after this lands:
* Fields in bundles and closures. The way this is done changes with #134811, so
  I rather implement this once both are in `main`.
* UI features for keeping sockets in sync (right now there are warnings only).

One bigger issue is the limited support for lazyness. For example, all inputs of
a Combine Bundle node will be evaluated, even if they are not all needed. The
same is true for all captured values of a closure. This is a deeper limitation
that needs to be resolved at some point. This will likely be done after an
initial version of this patch is done.

Pull Request: https://projects.blender.org/blender/blender/pulls/128340
2025-04-03 15:44:06 +02:00

116 lines
3.9 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*/
#pragma once
/**
* Geometry nodes has the concept of anonymous attributes. These are attributes that are created by
* some node with an internal name that is not exposed to the user. The only way to use this
* attribute is to make a link in the node tree to the node that should use it. This explicitness
* allows us to automatically determine when anonymous attributes are not needed anymore and should
* be deleted (or not created in the first place).
*
* This file is used to determine the lifetimes of these anonymous attributes. The logic is fairly
* straight forward to extend to other kinds of referenced data, but for now we only have anonymous
* attributes.
*
* The lifetime analysis uses information provided in the node declaration and hardcoded behavior
* for some special nodes like zones to determine the following things among others.
* - Where are new references (like anonymous attributes) created?
* - Which data sockets (like geometry) contain the referenced data?
* - Which nodes have to propagate which referenced data to which outputs?
*
* This information is later used when evaluating geometry nodes to reduce the lifetime of
* anonymous attributes automatically.
*/
#include "BLI_bit_group_vector.hh"
#include "BLI_vector.hh"
#include "DNA_node_types.h"
#include "NOD_node_declaration.hh"
namespace blender::bke::node_tree_reference_lifetimes {
enum class ReferenceSetType {
/**
* Corresponds to geometry outputs that may contain attributes that are propagated from a group
* input. In such cases, the caller may provide a set of attributes that should be propagated.
*/
GroupOutputData,
ClosureOutputData,
/**
* Field inputs may require attributes that need to be propagated from other geometry inputs to
* the node that evaluates the field.
*/
GroupInputReferenceSet,
ClosureInputReferenceSet,
/**
* Locally created anonymous attributes (like with the Capture Attribute node) need to be
* propagated to the nodes that use them or even to the group output.
*/
LocalReferenceSet,
};
struct ReferenceSetInfo {
ReferenceSetType type;
union {
/** Used for group interface sockets. */
int index;
/** Used for local and closure sockets. */
const bNodeSocket *socket;
};
/**
* Sockets that may contain the referenced data (e.g. the geometry output of a Capture Attribute
* node).
*/
Vector<const bNodeSocket *> potential_data_origins;
ReferenceSetInfo(ReferenceSetType type, const int index) : type(type), index(index)
{
BLI_assert(
ELEM(type, ReferenceSetType::GroupInputReferenceSet, ReferenceSetType::GroupOutputData));
}
ReferenceSetInfo(ReferenceSetType type, const bNodeSocket *socket) : type(type), socket(socket)
{
BLI_assert(ELEM(type,
ReferenceSetType::LocalReferenceSet,
ReferenceSetType::ClosureInputReferenceSet,
ReferenceSetType::ClosureOutputData));
}
friend std::ostream &operator<<(std::ostream &stream, const ReferenceSetInfo &info);
};
struct ReferenceLifetimesInfo {
Vector<ReferenceSetInfo> reference_sets;
/**
* Has a bit for each socket and each reference set. If the bit is set, the corresponding
* reference set should be propagated to that socket.
*/
BitGroupVector<> required_data_by_socket;
/**
* Relations used for group nodes that use this group.
*/
nodes::aal::RelationsInNode tree_relations;
};
bool analyse_reference_lifetimes(bNodeTree &tree);
/** The socket type allows storing references to data stored elsewhere. */
bool can_contain_reference(eNodeSocketDatatype socket_type);
/** The socket type allows storing data that may be referenced elsewhere. */
bool can_contain_referenced_data(eNodeSocketDatatype socket_type);
} // namespace blender::bke::node_tree_reference_lifetimes