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.
14 changed files with 123 additions and 2 deletions
Showing only changes of commit 24c7d5361c - Show all commits

View File

@ -9,6 +9,7 @@
#include "DNA_meshdata_types.h"
#include "FN_closure.hh"
#include "FN_init.h"
struct Tex;
@ -30,6 +31,8 @@ BLI_CPP_TYPE_MAKE(MStringProperty, CPPTypeFlags::None);
BLI_CPP_TYPE_MAKE(blender::bke::AnonymousAttributeSet, CPPTypeFlags::None);
BLI_CPP_TYPE_MAKE(blender::fn::Closure, CPPTypeFlags::None);
void BKE_cpp_types_init()
{
blender::register_cpp_types();
@ -49,4 +52,6 @@ void BKE_cpp_types_init()
BLI_CPP_TYPE_REGISTER(MStringProperty);
BLI_CPP_TYPE_REGISTER(blender::bke::AnonymousAttributeSet);
BLI_CPP_TYPE_REGISTER(blender::fn::Closure);
}

View File

@ -321,6 +321,7 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
break;
}
}
@ -466,6 +467,7 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
case __SOCK_MESH:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
BLI_assert_unreachable();
break;
}
@ -886,6 +888,7 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
break;
}
}
@ -981,6 +984,7 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
break;
}
}
@ -1627,6 +1631,7 @@ static void socket_id_user_increment(bNodeSocket *sock)
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
break;
}
}
@ -1673,6 +1678,7 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
case SOCK_CUSTOM:
case SOCK_SHADER:
case SOCK_GEOMETRY:
case SOCK_FUNCTION:
break;
}
return false;
@ -1855,6 +1861,8 @@ const char *nodeStaticSocketType(const int type, const int subtype)
return "NodeSocketTexture";
case SOCK_MATERIAL:
return "NodeSocketMaterial";
case SOCK_FUNCTION:
return "NodeSocketFunction";
default:
break;
}
@ -1934,6 +1942,8 @@ const char *nodeStaticSocketInterfaceType(const int type, const int subtype)
return "NodeSocketInterfaceTexture";
case SOCK_MATERIAL:
return "NodeSocketInterfaceMaterial";
case SOCK_FUNCTION:
return "NodeSocketInterfaceFunction";
default:
break;
}
@ -1969,6 +1979,8 @@ const char *nodeStaticSocketLabel(const int type, const int /*subtype*/)
return "Texture";
case SOCK_MATERIAL:
return "Material";
case SOCK_FUNCTION:
return "Function";
default:
break;
}

View File

@ -1198,6 +1198,7 @@ static const float std_node_socket_colors[][4] = {
{0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
{0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
{0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
{0.65, 0.05, 0.64, 1.0}, /* SOCK_FUNCTION */
};
/* common color callbacks for standard types */

View File

@ -2241,6 +2241,7 @@ static int get_main_socket_priority(const bNodeSocket *socket)
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
case SOCK_FUNCTION:
return 6;
}
return -1;

View File

@ -405,6 +405,9 @@ static Vector<NodeLinkItem> ui_node_link_items(NodeLinkArg *arg,
else if (dynamic_cast<const decl::Object *>(&socket_decl)) {
item.socket_type = SOCK_OBJECT;
}
else if (dynamic_cast<const decl::Function *>(&socket_decl)) {
item.socket_type = SOCK_FUNCTION;
}
else {
item.socket_type = SOCK_CUSTOM;
}

View File

@ -11,6 +11,7 @@ set(INC_SYS
)
set(SRC
intern/closure.cc
intern/cpp_types.cc
intern/field.cc
intern/field_cpp_type.cc
@ -26,6 +27,7 @@ set(SRC
intern/multi_function_procedure_executor.cc
intern/multi_function_procedure_optimization.cc
FN_closure.hh
FN_field.hh
FN_field_cpp_type.hh
FN_field_cpp_type_make.hh

View File

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup fn
*/
#include "BLI_cpp_type.hh"
#include "FN_lazy_function.hh"
#include "FN_lazy_function_graph_executor.hh"
namespace blender::fn {
class Closure {
private:
std::shared_ptr<lf::GraphExecutor> function_;
public:
Closure() = default;
Closure(const Closure &other) = default;
explicit Closure(const lf::GraphExecutor &function);
~Closure() = default;
Closure &operator=(const Closure &other) = default;
};
} // namespace blender::fn

View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup fn
*/
#include "FN_closure.hh"
namespace blender::fn {
Closure::Closure(const lf::GraphExecutor &function)
: function_(std::make_shared<lf::GraphExecutor>(function))
{
}
} // namespace blender::fn

View File

@ -236,6 +236,7 @@ typedef enum eNodeSocketDatatype {
SOCK_COLLECTION = 11,
SOCK_TEXTURE = 12,
SOCK_MATERIAL = 13,
SOCK_FUNCTION = 14,
} eNodeSocketDatatype;
/** Socket shape. */

View File

@ -72,6 +72,7 @@ static const EnumPropertyItem node_socket_data_type_items[] = {
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
{SOCK_FUNCTION, "FUNCTION", 0, "Function", ""},
{0, NULL, 0, NULL, NULL},
};
@ -100,6 +101,7 @@ static const EnumPropertyItem node_socket_type_items[] = {
{SOCK_COLLECTION, "COLLECTION", 0, "Collection", ""},
{SOCK_TEXTURE, "TEXTURE", 0, "Texture", ""},
{SOCK_MATERIAL, "MATERIAL", 0, "Material", ""},
{SOCK_FUNCTION, "FUNCTION", 0, "Function", ""},
{0, NULL, 0, NULL, NULL},
};
@ -2077,7 +2079,8 @@ static bool switch_type_supported(const EnumPropertyItem *item)
SOCK_COLLECTION,
SOCK_TEXTURE,
SOCK_MATERIAL,
SOCK_IMAGE);
SOCK_IMAGE,
SOCK_FUNCTION);
}
static const EnumPropertyItem *rna_GeometryNodeSwitch_type_itemf(bContext *UNUSED(C),
@ -11932,6 +11935,21 @@ static void rna_def_node_socket_material(BlenderRNA *brna,
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
}
static void rna_def_node_socket_function(BlenderRNA *brna,
const char *identifier,
const char *interface_idname)
{
StructRNA *srna;
srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
RNA_def_struct_ui_text(srna, "Function Node Socket", "Function socket of a node");
RNA_def_struct_sdna(srna, "bNodeSocket");
srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
RNA_def_struct_ui_text(srna, "Function Node Socket Interface", "Function socket of a node");
RNA_def_struct_sdna(srna, "bNodeSocket");
}
static void rna_def_node_socket_standard_types(BlenderRNA *brna)
{
/* XXX Workaround: Registered functions are not exposed in python by bpy,
@ -12084,6 +12102,8 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna)
rna_def_node_socket_texture(brna, "NodeSocketTexture", "NodeSocketInterfaceTexture");
rna_def_node_socket_material(brna, "NodeSocketMaterial", "NodeSocketInterfaceMaterial");
rna_def_node_socket_function(brna, "NodeSocketFunction", "NodeSocketInterfaceFunction");
}
static void rna_def_internal_node(BlenderRNA *brna)

View File

@ -225,6 +225,13 @@ class Shader : public SocketDeclaration {
class ShaderBuilder : public SocketDeclarationBuilder<Shader> {
};
class Function : public IDSocketDeclaration {
public:
using Builder = SocketDeclarationBuilder<Function>;
Function();
};
class ExtendBuilder;
class Extend : public SocketDeclaration {
@ -401,6 +408,10 @@ inline Texture::Texture() : IDSocketDeclaration("NodeSocketTexture") {}
inline Image::Image() : IDSocketDeclaration("NodeSocketImage") {}
inline Function::Function() : IDSocketDeclaration("NodeSocketFunction")
{
}
/** \} */
SocketDeclarationPtr create_extend_declaration(const eNodeSocketInOut in_out);

View File

@ -102,7 +102,8 @@ static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/,
SOCK_COLLECTION,
SOCK_TEXTURE,
SOCK_IMAGE,
SOCK_MATERIAL);
SOCK_MATERIAL,
SOCK_FUNCTION);
}
void register_node_tree_type_geo()

View File

@ -251,6 +251,9 @@ static SocketDeclarationPtr declaration_for_interface_socket(const bNodeTree &nt
dst = std::move(value);
break;
}
case SOCK_FUNCTION:
dst = std::make_unique<decl::Function>();
break;
case SOCK_CUSTOM:
std::unique_ptr<decl::Custom> decl = std::make_unique<decl::Custom>();
decl->idname_ = io_socket.idname;

View File

@ -33,6 +33,7 @@
#include "NOD_node_declaration.hh"
#include "NOD_socket.h"
#include "FN_closure.hh"
#include "FN_field.hh"
using namespace blender;
@ -778,6 +779,18 @@ static bNodeSocketType *make_socket_type_material()
return socktype;
}
static bNodeSocketType *make_socket_type_function()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_FUNCTION, PROP_NONE);
socktype->base_cpp_type = &blender::CPPType::get<fn::Closure>();
socktype->get_base_cpp_value = [](const bNodeSocket &/*socket*/, void *r_value) {
new (r_value) fn::Closure();
};
socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
return socktype;
}
void register_standard_node_socket_types()
{
/* Draw callbacks are set in `drawnode.c` to avoid bad-level calls. */
@ -824,5 +837,7 @@ void register_standard_node_socket_types()
nodeRegisterSocketType(make_socket_type_material());
nodeRegisterSocketType(make_socket_type_function());
nodeRegisterSocketType(make_socket_type_virtual());
}