WIP: Closures and deferred evaluation for geometry nodes #107842

Draft
Lukas Tönne wants to merge 35 commits from LukasTonne/blender:geometry-nodes-closures into main

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

View File

@ -7,6 +7,7 @@
*/
#include "BLI_cpp_type.hh"
#include "BLI_generic_pointer.hh"
namespace blender::nodes {
@ -15,16 +16,21 @@ struct GeometryNodesLazyFunctionGraphInfo;
class Closure {
private:
const GeometryNodesLazyFunctionGraphInfo *lf_graph_info_ = nullptr;
Vector<GMutablePointer> bound_values_;
public:
Closure() = default;
Closure(const Closure &other) = default;
explicit Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info);
~Closure() = default;
explicit Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
MutableSpan<GMutablePointer> &&bound_values);
~Closure();
Closure &operator=(const Closure &other) = default;
const GeometryNodesLazyFunctionGraphInfo *lf_graph_info() const;
Span<GMutablePointer> bound_values() const;
MutableSpan<GMutablePointer> bound_values();
};
} // namespace blender::nodes

View File

@ -37,12 +37,10 @@ static void node_declare(const bNodeTree &node_tree,
r_declaration.skip_updating_sockets = false;
LISTBASE_FOREACH (const bNodeSocket *, input, &group->inputs) {
r_declaration.inputs.append(declaration_for_interface_socket(node_tree, *input));
}
const FieldInferencingInterface &field_interface = *group->runtime->field_inferencing_interface;
for (const int i : r_declaration.inputs.index_range()) {
r_declaration.inputs[i]->input_field_type = field_interface.inputs[i];
SocketDeclarationPtr decl = declaration_for_interface_socket(node_tree, *input);
/* Need single values to bind. */
decl->input_field_type = InputSocketFieldType::None;
r_declaration.inputs.append(std::move(decl));
}
}
@ -54,16 +52,50 @@ static void node_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
{
if (params.node().id) {
const bNodeTree &bind_tree = *reinterpret_cast<bNodeTree *>(params.node().id);
const std::unique_ptr<GeometryNodesLazyFunctionGraphInfo> &lf_graph_info_ptr =
bind_tree.runtime->geometry_nodes_lazy_function_graph_info;
BLI_assert(lf_graph_info_ptr);
Closure closure(*lf_graph_info_ptr);
params.set_output("Function", std::move(closure));
if (params.node().id == nullptr) {
params.set_default_remaining_outputs();
return;
}
const bNodeTree &bind_tree = *reinterpret_cast<bNodeTree *>(params.node().id);
const std::unique_ptr<GeometryNodesLazyFunctionGraphInfo> &lf_graph_info_ptr =
bind_tree.runtime->geometry_nodes_lazy_function_graph_info;
BLI_assert(lf_graph_info_ptr);
Array<GMutablePointer> bound_values(params.node().input_sockets().size());
for (const int i : params.node().input_sockets().index_range()) {
const bNodeSocket *socket = params.node().input_sockets()[i];
const CPPType *cpptype = socket->typeinfo->geometry_nodes_cpp_type;
BLI_assert(cpptype != nullptr);
void *bound_value_buffer = MEM_mallocN_aligned(
cpptype->size(), cpptype->alignment(), "function bound value");
switch (socket->type) {
case SOCK_FLOAT:
float value = params.get_input<float>(socket->identifier);
cpptype->move_construct(&value, bound_value_buffer);
break;
case SOCK_VECTOR:
case SOCK_RGBA:
case SOCK_BOOLEAN:
case SOCK_INT:
case SOCK_STRING:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_GEOMETRY:
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
case SOCK_FUNCTION:
BLI_assert_unreachable();
}
bound_values[i] = {cpptype, bound_value_buffer};
}
Closure closure(*lf_graph_info_ptr, bound_values);
params.set_output("Function", std::move(closure));
params.set_default_remaining_outputs();
}

View File

@ -10,14 +10,27 @@
namespace blender::nodes {
Closure::Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info)
: lf_graph_info_(&lf_graph_info)
Closure::Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
MutableSpan<GMutablePointer> &&bound_values)
: lf_graph_info_(&lf_graph_info), bound_values_(std::move(bound_values))
{
}
Closure::~Closure() {}
const GeometryNodesLazyFunctionGraphInfo *Closure::lf_graph_info() const
{
return lf_graph_info_;
}
Span<GMutablePointer> Closure::bound_values() const
{
return bound_values_;
}
MutableSpan<GMutablePointer> Closure::bound_values()
{
return bound_values_;
}
} // namespace blender::nodes

View File

@ -1382,6 +1382,9 @@ class LazyFunctionForEvaluateFunctionNode : public LazyFunction {
Array<int> outer_output_indices(graph_outputs.size());
// TODO fill those arrays
// for (const int i :) {
// bound_inputs[i] = params.try_get_input_data_ptr_or_request;
//}
LinearAllocator allocator;
void *graph_executor_storage = graph_executor.init_storage(allocator);