Cleanup: Geometry Nodes: avoid unnecessary void pointer

All socket types use `SocketValueVariant` now, so using `void *` is not necessary anymore.

Pull Request: https://projects.blender.org/blender/blender/pulls/144415
This commit is contained in:
Jacques Lucke
2025-08-12 09:12:08 +02:00
parent 8d1e26865d
commit fbd29acaa2
9 changed files with 71 additions and 172 deletions

View File

@@ -92,11 +92,9 @@ static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
if (const auto *item_socket_value = std::get_if<nodes::BundleItemSocketValue>(
&bundle_item.value.value))
{
SocketValueVariant value_variant = item_socket_value->value;
if (std::unique_ptr<BakeItem> bake_item = move_common_socket_value_to_bake_item(
*item_socket_value->type,
*static_cast<SocketValueVariant *>(item_socket_value->value),
std::nullopt,
r_geometry_bake_items))
*item_socket_value->type, value_variant, std::nullopt, r_geometry_bake_items))
{
bundle_bake_item->items.append(
BundleBakeItem::Item{bundle_item.key,
@@ -297,7 +295,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(
copy_bake_item_to_socket_value(
*socket_value->value, stype->type, {}, data_block_map, r_attribute_map))
{
bundle.add(item.key, nodes::BundleItemSocketValue{stype, &*child_value_variant});
bundle.add(item.key, nodes::BundleItemSocketValue{stype, *child_value_variant});
}
else {
return std::nullopt;

View File

@@ -18,7 +18,7 @@ struct BundleItemSocketValue {
/** The type of data referenced. It uses #bNodeSocketType::geometry_nodes_cpp_type. */
const bke::bNodeSocketType *type;
/** Non-owning pointer to the value. The memory is owned by the Bundle directly. */
void *value;
bke::SocketValueVariant value;
};
/**
@@ -60,16 +60,8 @@ class Bundle : public ImplicitSharingMixin {
private:
Vector<StoredItem> items_;
Vector<void *> buffers_;
public:
Bundle();
Bundle(const Bundle &other);
Bundle(Bundle &&other) noexcept;
Bundle &operator=(const Bundle &other);
Bundle &operator=(Bundle &&other) noexcept;
~Bundle();
static BundlePtr create();
bool add(StringRef key, const BundleItemValue &value);
@@ -115,21 +107,15 @@ inline std::optional<T> BundleItemValue::as_socket_value(
if (!socket_value) {
return std::nullopt;
}
if (!socket_value->value || !socket_value->type) {
return std::nullopt;
if (socket_value->type->type == dst_socket_type.type) {
return socket_value->value.get<T>();
}
const void *converted_value = socket_value->value;
BUFFER_FOR_CPP_TYPE_VALUE(*dst_socket_type.geometry_nodes_cpp_type, buffer);
if (socket_value->type != &dst_socket_type) {
if (!implicitly_convert_socket_value(
*socket_value->type, socket_value->value, dst_socket_type, buffer))
{
return std::nullopt;
}
converted_value = buffer;
if (std::optional<bke::SocketValueVariant> converted_value = implicitly_convert_socket_value(
*socket_value->type, socket_value->value, dst_socket_type))
{
return converted_value->get<T>();
}
const auto &value_variant = *static_cast<const bke::SocketValueVariant *>(converted_value);
return value_variant.get<T>();
return std::nullopt;
}
template<typename T> inline const bke::bNodeSocketType *socket_type_info_by_static_type()
@@ -183,15 +169,8 @@ template<typename T> inline std::optional<T> BundleItemValue::as() const
if (!socket_value) {
return std::nullopt;
}
if (!socket_value->value || !socket_value->type) {
return std::nullopt;
}
if (!socket_value->type->geometry_nodes_cpp_type->is<bke::SocketValueVariant>()) {
return std::nullopt;
}
const auto *value = static_cast<const bke::SocketValueVariant *>(socket_value->value);
if (value->is_list()) {
return value->get<ListPtr>();
if (socket_value->value.is_list()) {
return socket_value->value.get<ListPtr>();
}
return std::nullopt;
}
@@ -242,7 +221,7 @@ template<typename T, typename Fn> inline void to_stored_type(T &&value, Fn &&fn)
}
else if (const bke::bNodeSocketType *socket_type = socket_type_info_by_static_type<DecayT>()) {
auto value_variant = bke::SocketValueVariant::From(std::forward<T>(value));
fn(BundleItemValue{BundleItemSocketValue{socket_type, &value_variant}});
fn(BundleItemValue{BundleItemSocketValue{socket_type, value_variant}});
}
else {
/* All allowed types should be handled above already. */

View File

@@ -8,17 +8,16 @@
#include "NOD_geometry_nodes_lazy_function.hh"
#include "BKE_node_socket_value.hh"
namespace blender::nodes {
struct ClosureEagerEvalParams {
struct InputItem {
std::string key;
const bke::bNodeSocketType *type = nullptr;
/**
* The actual socket value of type bNodeSocketType::geometry_nodes_cpp_type.
* This is not const, because it may be moved from.
*/
void *value = nullptr;
/** This may be moved from. */
bke::SocketValueVariant value;
};
struct OutputItem {
@@ -28,7 +27,7 @@ struct ClosureEagerEvalParams {
* Where the output value should be stored. This is expected to point to uninitialized memory
* when it's passed into #evaluate_closure_eagerly which will then construct the value inplace.
*/
void *value = nullptr;
bke::SocketValueVariant *value = nullptr;
};
Vector<InputItem> inputs;

View File

@@ -56,10 +56,10 @@ template<typename T> constexpr bool is_GeoNodesMultiInput_v<GeoNodesMultiInput<T
* Performs implicit conversion between socket types. Returns false if the conversion is not
* possible. In that case, r_to_value is left uninitialized.
*/
[[nodiscard]] bool implicitly_convert_socket_value(const bke::bNodeSocketType &from_type,
const void *from_value,
const bke::bNodeSocketType &to_type,
void *r_to_value);
[[nodiscard]] std::optional<bke::SocketValueVariant> implicitly_convert_socket_value(
const bke::bNodeSocketType &from_type,
const bke::SocketValueVariant &from_value,
const bke::bNodeSocketType &to_type);
/**
* Builds a lazy-function that can convert between socket types. Returns null if the conversion is

View File

@@ -122,9 +122,9 @@ static void node_geo_exec(GeoNodeExecParams params)
if (name.is_empty()) {
continue;
}
void *input_ptr = params.low_level_lazy_function_params().try_get_input_data_ptr(i);
BLI_assert(input_ptr);
bundle.add(name, BundleItemSocketValue{stype, input_ptr});
bke::SocketValueVariant value = params.extract_input<bke::SocketValueVariant>(
node.input_socket(i).identifier);
bundle.add(name, BundleItemSocketValue{stype, std::move(value)});
}
params.set_output("Bundle", std::move(bundle_ptr));

View File

@@ -144,14 +144,13 @@ static void node_geo_exec(GeoNodeExecParams params)
fmt::format("{}: \"{}\"", TIP_("Cannot get internal value from bundle"), name));
continue;
}
void *output_ptr = lf_params.get_output_data_ptr(i);
if (socket_value->type->type == stype->type) {
socket_value->type->geometry_nodes_cpp_type->copy_construct(socket_value->value, output_ptr);
}
else {
if (implicitly_convert_socket_value(
*socket_value->type, socket_value->value, *stype, output_ptr))
SocketValueVariant output_value = std::move(socket_value->value);
if (socket_value->type->type != stype->type) {
if (std::optional<SocketValueVariant> converted_value = implicitly_convert_socket_value(
*socket_value->type, output_value, *stype))
{
output_value = std::move(*converted_value);
params.error_message_add(
NodeWarningType::Info,
fmt::format("{}: \"{}\" ({} " BLI_STR_UTF8_BLACK_RIGHT_POINTING_SMALL_TRIANGLE " {})",
@@ -168,10 +167,10 @@ static void node_geo_exec(GeoNodeExecParams params)
name,
TIP_(socket_value->type->label),
TIP_(stype->label)));
construct_socket_default_value(*stype, output_ptr);
output_value = *socket_value->type->geometry_nodes_default_value;
}
}
lf_params.output_set(i);
lf_params.set_output(i, std::move(output_value));
}
params.set_default_remaining_outputs();

View File

@@ -43,59 +43,11 @@ bool BundleSignature::all_matching_exactly(const Span<BundleSignature> signature
return true;
}
Bundle::Bundle() = default;
Bundle::~Bundle()
{
for (StoredItem &item : items_) {
if (BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(
&item.value.value))
{
socket_value->type->geometry_nodes_cpp_type->destruct(socket_value->value);
}
}
for (void *buffer : buffers_) {
MEM_freeN(buffer);
}
}
Bundle::Bundle(const Bundle &other)
{
for (const StoredItem &item : other.items_) {
this->add_new(item.key, item.value);
}
}
Bundle::Bundle(Bundle &&other) noexcept
: items_(std::move(other.items_)), buffers_(std::move(other.buffers_))
{
}
BundlePtr Bundle::create()
{
return BundlePtr(MEM_new<Bundle>(__func__));
}
Bundle &Bundle::operator=(const Bundle &other)
{
if (this == &other) {
return *this;
}
this->~Bundle();
new (this) Bundle(other);
return *this;
}
Bundle &Bundle::operator=(Bundle &&other) noexcept
{
if (this == &other) {
return *this;
}
this->~Bundle();
new (this) Bundle(std::move(other));
return *this;
}
[[maybe_unused]] static bool is_valid_key(const StringRef key)
{
return key.find('/') == StringRef::not_found;
@@ -104,22 +56,7 @@ Bundle &Bundle::operator=(Bundle &&other) noexcept
void Bundle::add_new(const StringRef key, const BundleItemValue &value)
{
BLI_assert(is_valid_key(key));
if (const BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(&value.value))
{
const bke::bNodeSocketType &type = *socket_value->type;
BLI_assert(type.geometry_nodes_cpp_type);
const CPPType &cpp_type = *type.geometry_nodes_cpp_type;
void *buffer = MEM_mallocN_aligned(cpp_type.size, cpp_type.alignment, __func__);
cpp_type.copy_construct(socket_value->value, buffer);
items_.append(StoredItem{std::move(key), {BundleItemSocketValue{&type, buffer}}});
buffers_.append(buffer);
}
else if (std::holds_alternative<BundleItemInternalValue>(value.value)) {
items_.append(StoredItem{std::move(key), value});
}
else {
BLI_assert_unreachable();
}
items_.append(StoredItem{std::move(key), value});
}
void Bundle::add_override(const StringRef key, const BundleItemValue &value)
@@ -164,7 +101,7 @@ void Bundle::add_path_override(const StringRef path, const BundleItemValue &valu
std::move(child_bundle));
this->add(
first_part,
BundleItemSocketValue{bke::node_socket_type_find_static(SOCK_BUNDLE), &child_bundle_value});
BundleItemSocketValue{bke::node_socket_type_find_static(SOCK_BUNDLE), child_bundle_value});
}
bool Bundle::add_path(StringRef path, const BundleItemValue &value)
@@ -245,17 +182,7 @@ BundlePtr Bundle::copy() const
bool Bundle::remove(const StringRef key)
{
BLI_assert(is_valid_key(key));
const int removed_num = items_.remove_if([&key](StoredItem &item) {
if (item.key == key) {
if (BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(
&item.value.value))
{
socket_value->type->geometry_nodes_cpp_type->destruct(socket_value->value);
}
return true;
}
return false;
});
const int removed_num = items_.remove_if([&key](StoredItem &item) { return item.key == key; });
return removed_num >= 1;
}

View File

@@ -788,18 +788,18 @@ void evaluate_closure_eagerly(const Closure &closure, ClosureEagerEvalParams &pa
if (const std::optional<int> mapped_i = inputs_map[input_item_i]) {
const bke::bNodeSocketType &from_type = *item.type;
const bke::bNodeSocketType &to_type = *signature.inputs[*mapped_i].type;
const CPPType &to_cpp_type = *to_type.geometry_nodes_cpp_type;
void *value = allocator.allocate(to_cpp_type);
if (&from_type == &to_type) {
to_cpp_type.copy_construct(item.value, value);
bke::SocketValueVariant input_value;
if (std::optional<bke::SocketValueVariant> value = implicitly_convert_socket_value(
from_type, item.value, to_type))
{
input_value = *value;
}
else {
if (!implicitly_convert_socket_value(from_type, item.value, to_type, value)) {
const void *default_value = closure.default_input_value(*mapped_i);
to_cpp_type.copy_construct(default_value, value);
}
input_value = *to_type.geometry_nodes_default_value;
}
lf_input_values[indices.inputs.main[*mapped_i]] = {to_cpp_type, value};
lf_input_values[indices.inputs.main[*mapped_i]] = {
CPPType::get<bke::SocketValueVariant>(),
allocator.construct<bke::SocketValueVariant>(std::move(input_value)).release()};
}
else {
/* Provided input value is ignored. */
@@ -859,15 +859,15 @@ void evaluate_closure_eagerly(const Closure &closure, ClosureEagerEvalParams &pa
if (const std::optional<int> mapped_i = outputs_map[output_item_i]) {
const bke::bNodeSocketType &from_type = *signature.outputs[*mapped_i].type;
const bke::bNodeSocketType &to_type = *item.type;
const CPPType &to_cpp_type = *to_type.geometry_nodes_cpp_type;
void *computed_value = lf_output_values[indices.outputs.main[*mapped_i]].get();
if (&from_type == &to_type) {
to_cpp_type.move_construct(computed_value, item.value);
if (std::optional<bke::SocketValueVariant> value = implicitly_convert_socket_value(
from_type,
*lf_output_values[indices.outputs.main[*mapped_i]].get<bke::SocketValueVariant>(),
to_type))
{
new (item.value) bke::SocketValueVariant(std::move(*value));
}
else {
if (!implicitly_convert_socket_value(from_type, computed_value, to_type, item.value)) {
construct_socket_default_value(to_type, item.value);
}
new (item.value) bke::SocketValueVariant(*to_type.geometry_nodes_default_value);
}
}
else {

View File

@@ -548,37 +548,34 @@ static void execute_multi_function_on_value_variant__field(
return true;
}
bool implicitly_convert_socket_value(const bke::bNodeSocketType &from_type,
const void *from_value,
const bke::bNodeSocketType &to_type,
void *r_to_value)
std::optional<SocketValueVariant> implicitly_convert_socket_value(
const bke::bNodeSocketType &from_type,
const SocketValueVariant &from_value,
const bke::bNodeSocketType &to_type)
{
BLI_assert(from_value != r_to_value);
if (from_type.type == to_type.type) {
from_type.geometry_nodes_cpp_type->copy_construct(from_value, r_to_value);
return true;
return from_value;
}
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
const CPPType *from_cpp_type = from_type.base_cpp_type;
const CPPType *to_cpp_type = to_type.base_cpp_type;
if (!from_cpp_type || !to_cpp_type) {
return false;
return std::nullopt;
}
if (conversions.is_convertible(*from_cpp_type, *to_cpp_type)) {
const MultiFunction &multi_fn = *conversions.get_conversion_multi_function(
mf::DataType::ForSingle(*from_cpp_type), mf::DataType::ForSingle(*to_cpp_type));
SocketValueVariant input_variant = *static_cast<const SocketValueVariant *>(from_value);
SocketValueVariant *output_variant = new (r_to_value) SocketValueVariant();
SocketValueVariant input_variant = from_value;
SocketValueVariant output_variant;
std::string error_message;
if (!execute_multi_function_on_value_variant(
multi_fn, {}, {&input_variant}, {output_variant}, nullptr, error_message))
multi_fn, {}, {&input_variant}, {&output_variant}, nullptr, error_message))
{
std::destroy_at(output_variant);
return false;
return std::nullopt;
}
return true;
return output_variant;
}
return false;
return std::nullopt;
}
class LazyFunctionForImplicitConversion : public LazyFunction {
@@ -691,16 +688,16 @@ class LazyFunctionForMutedNode : public LazyFunction {
continue;
}
const int lf_input_index = lf_index_by_bsocket_[input_bsocket->index_in_tree()];
const void *input_value = params.try_get_input_data_ptr_or_request(lf_input_index);
if (input_value == nullptr) {
const SocketValueVariant *input_value =
params.try_get_input_data_ptr_or_request<SocketValueVariant>(lf_input_index);
if (!input_value) {
/* Wait for value to be available. */
continue;
}
void *output_value = params.get_output_data_ptr(lf_output_index);
if (implicitly_convert_socket_value(
*input_bsocket->typeinfo, input_value, *output_bsocket->typeinfo, output_value))
if (std::optional<SocketValueVariant> converted_value = implicitly_convert_socket_value(
*input_bsocket->typeinfo, *input_value, *output_bsocket->typeinfo))
{
params.output_set(lf_output_index);
params.set_output(lf_output_index, std::move(*converted_value));
continue;
}
set_default_value_for_output_socket(params, lf_output_index, *output_bsocket);