Refactor: Geometry Nodes: use SocketValueVariant in bake api

This simplifies the bake API used by Geometry Nodes by using `SocketValueVariant`
 instead of raw pointers. This is possible now, because all socket types use
`SocketValueVariant` under the hood.

Pull Request: https://projects.blender.org/blender/blender/pulls/144410
This commit is contained in:
Jacques Lucke
2025-08-12 07:59:18 +02:00
parent d9410660ca
commit 7c5f7434f2
5 changed files with 231 additions and 312 deletions

View File

@@ -14,6 +14,7 @@
#include "BKE_bake_items.hh"
#include "BKE_geometry_fields.hh"
#include "BKE_node_socket_value.hh"
namespace blender::bke::bake {
@@ -42,7 +43,9 @@ struct BakeSocketConfig {
* be in a moved-from state afterwards.
*/
Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(
Span<void *> socket_values, const BakeSocketConfig &config, BakeDataBlockMap *data_block_map);
MutableSpan<SocketValueVariant> socket_values,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map);
/**
* Create socket values from bake items.
@@ -52,26 +55,22 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(
*
* \param make_attribute_field: A function that creates a field input for any anonymous attributes
* being created for the baked data.
* \param r_socket_values: The caller is expected to allocate (but not construct) the output
* values. All socket values are constructed in this function.
*/
void move_bake_items_to_socket_values(
Vector<SocketValueVariant> move_bake_items_to_socket_values(
Span<BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int socket_index, const CPPType &)>
make_attribute_field,
Span<void *> r_socket_values);
make_attribute_field);
/**
* Similar to #move_bake_items_to_socket_values, but does not change the bake items. Hence, this
* should be used when the bake items are still used later on.
*/
void copy_bake_items_to_socket_values(
Vector<SocketValueVariant> copy_bake_items_to_socket_values(
Span<const BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
Span<void *> r_socket_values);
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field);
} // namespace blender::bke::bake

View File

@@ -41,21 +41,19 @@ static void capture_field_on_geometry_components(GeometrySet &geometry,
static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
const bNodeSocketType &stype,
void *socket_value,
SocketValueVariant &socket_value,
std::optional<StringRef> name,
Vector<GeometryBakeItem *> &r_geometry_bake_items)
{
switch (stype.type) {
case SOCK_GEOMETRY: {
GeometrySet geometry =
static_cast<SocketValueVariant *>(socket_value)->extract<GeometrySet>();
GeometrySet geometry = socket_value.extract<GeometrySet>();
auto item = std::make_unique<GeometryBakeItem>(std::move(geometry));
r_geometry_bake_items.append(item.get());
return item;
}
case SOCK_STRING: {
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
return std::make_unique<StringBakeItem>(value_variant.extract<std::string>());
return std::make_unique<StringBakeItem>(socket_value.extract<std::string>());
}
case SOCK_FLOAT:
case SOCK_VECTOR:
@@ -64,14 +62,13 @@ static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_RGBA: {
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
if (value_variant.is_context_dependent_field()) {
if (socket_value.is_context_dependent_field()) {
/* Not supported here because it's not known which geometry this field belongs to. */
return {};
}
#ifdef WITH_OPENVDB
if (value_variant.is_volume_grid()) {
bke::GVolumeGrid grid = value_variant.get<bke::GVolumeGrid>();
if (socket_value.is_volume_grid()) {
bke::GVolumeGrid grid = socket_value.get<bke::GVolumeGrid>();
if (name) {
grid.get_for_write().set_name(*name);
}
@@ -82,26 +79,29 @@ static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
UNUSED_VARS(name);
#endif
value_variant.convert_to_single();
GPointer value = value_variant.get_single_ptr();
socket_value.convert_to_single();
GPointer value = socket_value.get_single_ptr();
return std::make_unique<PrimitiveBakeItem>(*value.type(), value.get());
}
case SOCK_BUNDLE: {
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
nodes::BundlePtr bundle_ptr = value_variant.extract<nodes::BundlePtr>();
nodes::BundlePtr bundle_ptr = socket_value.extract<nodes::BundlePtr>();
auto bundle_bake_item = std::make_unique<BundleBakeItem>();
if (bundle_ptr) {
const nodes::Bundle &bundle = *bundle_ptr;
for (const nodes::Bundle::StoredItem &bundle_item : bundle.items()) {
if (const auto *socket_value = std::get_if<nodes::BundleItemSocketValue>(
if (const auto *item_socket_value = std::get_if<nodes::BundleItemSocketValue>(
&bundle_item.value.value))
{
if (std::unique_ptr<BakeItem> bake_item = move_common_socket_value_to_bake_item(
*socket_value->type, socket_value->value, std::nullopt, r_geometry_bake_items))
*item_socket_value->type,
*static_cast<SocketValueVariant *>(item_socket_value->value),
std::nullopt,
r_geometry_bake_items))
{
bundle_bake_item->items.append(BundleBakeItem::Item{
bundle_item.key,
BundleBakeItem::SocketValue{socket_value->type->idname, std::move(bake_item)}});
bundle_bake_item->items.append(
BundleBakeItem::Item{bundle_item.key,
BundleBakeItem::SocketValue{item_socket_value->type->idname,
std::move(bake_item)}});
}
}
else if (const auto *internal_value = std::get_if<nodes::BundleItemInternalValue>(
@@ -124,9 +124,10 @@ static std::unique_ptr<BakeItem> move_common_socket_value_to_bake_item(
}
}
Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<void *> socket_values,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map)
Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(
MutableSpan<SocketValueVariant> socket_values,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map)
{
BLI_assert(socket_values.size() == config.types.size());
BLI_assert(socket_values.size() == config.geometries_by_attribute.size());
@@ -141,8 +142,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
if (socket_type != SOCK_GEOMETRY) {
continue;
}
void *socket_value = socket_values[i];
GeometrySet geometry = static_cast<SocketValueVariant *>(socket_value)->extract<GeometrySet>();
GeometrySet geometry = socket_values[i].extract<GeometrySet>();
auto geometry_item = std::make_unique<GeometryBakeItem>(std::move(geometry));
geometry_bake_items.append(geometry_item.get());
bake_items[i] = std::move(geometry_item);
@@ -151,7 +151,7 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
for (const int i : socket_values.index_range()) {
const eNodeSocketDatatype socket_type = config.types[i];
const bNodeSocketType &stype = *node_socket_type_find_static(socket_type);
void *socket_value = socket_values[i];
SocketValueVariant &socket_value = socket_values[i];
switch (socket_type) {
case SOCK_GEOMETRY: {
/* Handled already. */
@@ -169,9 +169,8 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
case SOCK_ROTATION:
case SOCK_MATRIX:
case SOCK_RGBA: {
auto &value_variant = *static_cast<SocketValueVariant *>(socket_value);
if (value_variant.is_context_dependent_field()) {
const fn::GField &field = value_variant.get<fn::GField>();
if (socket_value.is_context_dependent_field()) {
const fn::GField &field = socket_value.get<fn::GField>();
const AttrDomain domain = config.domains[i];
const std::string attribute_name = ".bake_" + std::to_string(i);
const Span<int> geometry_indices = config.geometries_by_attribute[i];
@@ -216,24 +215,22 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
/**
* \return True if #r_value has been constructed.
*/
[[nodiscard]] static bool copy_bake_item_to_socket_value(
[[nodiscard]] static std::optional<SocketValueVariant> copy_bake_item_to_socket_value(
const BakeItem &bake_item,
const eNodeSocketDatatype socket_type,
const FunctionRef<std::shared_ptr<AttributeFieldInput>(const CPPType &type)>
make_attribute_field,
BakeDataBlockMap *data_block_map,
Map<std::string, std::string> &r_attribute_map,
void *r_value)
Map<std::string, std::string> &r_attribute_map)
{
switch (socket_type) {
case SOCK_GEOMETRY: {
if (const auto *item = dynamic_cast<const GeometryBakeItem *>(&bake_item)) {
bke::GeometrySet geometry = item->geometry;
GeometryBakeItem::try_restore_data_blocks(geometry, data_block_map);
SocketValueVariant::ConstructIn(r_value, std::move(geometry));
return true;
return SocketValueVariant::From(std::move(geometry));
}
return false;
return std::nullopt;
}
case SOCK_FLOAT:
case SOCK_VECTOR:
@@ -245,21 +242,20 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
const CPPType &base_type = *socket_type_to_geo_nodes_base_cpp_type(socket_type);
if (const auto *item = dynamic_cast<const PrimitiveBakeItem *>(&bake_item)) {
if (item->type() == base_type) {
auto *value_variant = new (r_value) SocketValueVariant();
value_variant->store_single(socket_type, item->value());
return true;
SocketValueVariant value_variant;
value_variant.store_single(socket_type, item->value());
return value_variant;
}
return false;
return std::nullopt;
}
if (const auto *item = dynamic_cast<const AttributeBakeItem *>(&bake_item)) {
if (!make_attribute_field) {
return false;
return std::nullopt;
}
std::shared_ptr<AttributeFieldInput> attribute_field = make_attribute_field(base_type);
r_attribute_map.add(item->name(), attribute_field->attribute_name());
fn::GField field{attribute_field};
SocketValueVariant::ConstructIn(r_value, std::move(field));
return true;
return SocketValueVariant::From(std::move(field));
}
#ifdef WITH_OPENVDB
if (const auto *item = dynamic_cast<const VolumeGridBakeItem *>(&bake_item)) {
@@ -268,23 +264,21 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
const std::optional<eNodeSocketDatatype> grid_socket_type = grid_type_to_socket_type(
grid_type);
if (!grid_socket_type) {
return false;
return std::nullopt;
}
if (grid_socket_type == socket_type) {
bke::SocketValueVariant::ConstructIn(r_value, *item->grid);
return true;
return bke::SocketValueVariant::From(*item->grid);
}
return false;
return std::nullopt;
}
#endif
return false;
return std::nullopt;
}
case SOCK_STRING: {
if (const auto *item = dynamic_cast<const StringBakeItem *>(&bake_item)) {
new (r_value) SocketValueVariant(std::string(item->value()));
return true;
return SocketValueVariant(std::string(item->value()));
}
return false;
return std::nullopt;
}
case SOCK_BUNDLE: {
if (const auto *item = dynamic_cast<const BundleBakeItem *>(&bake_item)) {
@@ -294,23 +288,20 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
if (const auto *socket_value = std::get_if<BundleBakeItem::SocketValue>(&item.value)) {
const bNodeSocketType *stype = node_socket_type_find(socket_value->socket_idname);
if (!stype) {
return false;
return std::nullopt;
}
if (!stype->geometry_nodes_cpp_type) {
return false;
return std::nullopt;
}
BUFFER_FOR_CPP_TYPE_VALUE(*stype->geometry_nodes_cpp_type, buffer);
if (!copy_bake_item_to_socket_value(*socket_value->value,
stype->type,
{},
data_block_map,
r_attribute_map,
buffer))
if (std::optional<SocketValueVariant> child_value_variant =
copy_bake_item_to_socket_value(
*socket_value->value, stype->type, {}, data_block_map, r_attribute_map))
{
return false;
bundle.add(item.key, nodes::BundleItemSocketValue{stype, &*child_value_variant});
}
else {
return std::nullopt;
}
bundle.add(item.key, nodes::BundleItemSocketValue{stype, buffer});
stype->geometry_nodes_cpp_type->destruct(buffer);
}
if (const auto *internal_value = std::get_if<BundleBakeItem::InternalValue>(&item.value))
{
@@ -324,15 +315,14 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
nodes::BundleItemInternalValue{ImplicitSharingPtr{internal_data}});
}
}
bke::SocketValueVariant::ConstructIn(r_value, std::move(bundle_ptr));
return true;
return bke::SocketValueVariant::From(std::move(bundle_ptr));
}
return false;
return std::nullopt;
}
default:
return false;
return std::nullopt;
}
return false;
return std::nullopt;
}
static void rename_attributes(const Span<GeometrySet *> geometries,
@@ -366,95 +356,98 @@ static void rename_attributes(const Span<GeometrySet *> geometries,
}
}
static void default_initialize_socket_value(const eNodeSocketDatatype socket_type, void *r_value)
static SocketValueVariant default_initialize_socket_value(const eNodeSocketDatatype socket_type)
{
const bke::bNodeSocketType *typeinfo = bke::node_socket_type_find_static(socket_type);
if (typeinfo->geometry_nodes_default_cpp_value) {
typeinfo->geometry_nodes_cpp_type->copy_construct(typeinfo->geometry_nodes_default_cpp_value,
r_value);
}
else {
typeinfo->geometry_nodes_cpp_type->value_initialize(r_value);
}
return *static_cast<const SocketValueVariant *>(typeinfo->geometry_nodes_default_cpp_value);
}
void move_bake_items_to_socket_values(
Vector<SocketValueVariant> move_bake_items_to_socket_values(
const Span<BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
const Span<void *> r_socket_values)
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field)
{
Map<std::string, std::string> attribute_map;
Vector<GeometrySet *> geometries;
Vector<SocketValueVariant> socket_values;
socket_values.reserve(bake_items.size());
for (const int i : bake_items.index_range()) {
const eNodeSocketDatatype socket_type = config.types[i];
BakeItem *bake_item = bake_items[i];
void *r_socket_value = r_socket_values[i];
if (bake_item == nullptr) {
default_initialize_socket_value(socket_type, r_socket_value);
socket_values.append(default_initialize_socket_value(socket_type));
continue;
}
if (!copy_bake_item_to_socket_value(
if (std::optional<SocketValueVariant> socket_value = copy_bake_item_to_socket_value(
*bake_item,
socket_type,
[&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
data_block_map,
attribute_map,
r_socket_value))
attribute_map))
{
default_initialize_socket_value(socket_type, r_socket_value);
socket_values.append(std::move(*socket_value));
}
else {
socket_values.append(default_initialize_socket_value(socket_type));
continue;
}
if (socket_type == SOCK_GEOMETRY) {
auto &item = *static_cast<GeometryBakeItem *>(bake_item);
item.geometry.clear();
geometries.append(
static_cast<SocketValueVariant *>(r_socket_value)->get_single_ptr().get<GeometrySet>());
}
}
rename_attributes(geometries, attribute_map);
for (SocketValueVariant &socket_value : socket_values) {
if (socket_value.valid_for_socket(SOCK_GEOMETRY)) {
GeometrySet *geometry = socket_value.get_single_ptr().get<GeometrySet>();
rename_attributes({geometry}, attribute_map);
}
}
return socket_values;
}
void copy_bake_items_to_socket_values(
Vector<SocketValueVariant> copy_bake_items_to_socket_values(
const Span<const BakeItem *> bake_items,
const BakeSocketConfig &config,
BakeDataBlockMap *data_block_map,
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field,
const Span<void *> r_socket_values)
FunctionRef<std::shared_ptr<AttributeFieldInput>(int, const CPPType &)> make_attribute_field)
{
Map<std::string, std::string> attribute_map;
Vector<GeometrySet *> geometries;
Vector<SocketValueVariant> socket_values;
socket_values.reserve(bake_items.size());
for (const int i : bake_items.index_range()) {
const eNodeSocketDatatype socket_type = config.types[i];
const BakeItem *bake_item = bake_items[i];
void *r_socket_value = r_socket_values[i];
if (bake_item == nullptr) {
default_initialize_socket_value(socket_type, r_socket_value);
socket_values.append(default_initialize_socket_value(socket_type));
continue;
}
if (!copy_bake_item_to_socket_value(
if (std::optional<SocketValueVariant> socket_value = copy_bake_item_to_socket_value(
*bake_item,
socket_type,
[&](const CPPType &attr_type) { return make_attribute_field(i, attr_type); },
data_block_map,
attribute_map,
r_socket_value))
attribute_map))
{
default_initialize_socket_value(socket_type, r_socket_value);
continue;
socket_values.append(std::move(*socket_value));
}
if (socket_type == SOCK_GEOMETRY) {
geometries.append(
static_cast<SocketValueVariant *>(r_socket_value)->get_single_ptr().get<GeometrySet>());
else {
socket_values.append(default_initialize_socket_value(socket_type));
}
}
rename_attributes(geometries, attribute_map);
for (SocketValueVariant &socket_value : socket_values) {
if (socket_value.valid_for_socket(SOCK_GEOMETRY)) {
GeometrySet *geometry = socket_value.get_single_ptr().get<GeometrySet>();
rename_attributes({geometry}, attribute_map);
}
}
return socket_values;
}
} // namespace blender::bke::bake

View File

@@ -56,8 +56,8 @@ void get_closest_in_bvhtree(bke::BVHTreeFromMesh &tree_data,
MutableSpan<float3> r_positions);
void mix_baked_data_item(eNodeSocketDatatype socket_type,
void *prev,
const void *next,
SocketValueVariant &prev,
const SocketValueVariant &next,
const float factor);
namespace enums {

View File

@@ -315,17 +315,13 @@ class LazyFunctionForBakeNode final : public LazyFunction {
/* Wait for inputs to be computed. */
return;
}
Array<void *> output_values(bake_items_.size());
Vector<SocketValueVariant> output_values = this->move_bake_state_to_values(
std::move(*bake_state),
data_block_map,
*user_data.call_data->self_object(),
*user_data.compute_context);
for (const int i : bake_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
this->move_bake_state_to_values(std::move(*bake_state),
data_block_map,
*user_data.call_data->self_object(),
*user_data.compute_context,
output_values);
for (const int i : bake_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(output_values[i]));
}
}
@@ -349,17 +345,13 @@ class LazyFunctionForBakeNode final : public LazyFunction {
bke::bake::BakeDataBlockMap *data_block_map,
const bake::BakeStateRef &bake_state) const
{
Array<void *> output_values(bake_items_.size());
Vector<SocketValueVariant> values = this->copy_bake_state_to_values(
bake_state,
data_block_map,
*user_data.call_data->self_object(),
*user_data.compute_context);
for (const int i : bake_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
this->copy_bake_state_to_values(bake_state,
data_block_map,
*user_data.call_data->self_object(),
*user_data.compute_context,
output_values);
for (const int i : bake_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(values[i]));
}
}
@@ -371,51 +363,39 @@ class LazyFunctionForBakeNode final : public LazyFunction {
const bake::BakeStateRef &next_state,
const float mix_factor) const
{
Array<void *> output_values(bake_items_.size());
for (const int i : bake_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
this->copy_bake_state_to_values(
prev_state, data_block_map, self_object, compute_context, output_values);
Array<void *> next_values(bake_items_.size());
LinearAllocator<> allocator;
for (const int i : bake_items_.index_range()) {
const CPPType &type = *outputs_[i].type;
next_values[i] = allocator.allocate(type);
}
this->copy_bake_state_to_values(
next_state, data_block_map, self_object, compute_context, next_values);
Vector<SocketValueVariant> output_values = this->copy_bake_state_to_values(
prev_state, data_block_map, self_object, compute_context);
Vector<SocketValueVariant> next_values = this->copy_bake_state_to_values(
next_state, data_block_map, self_object, compute_context);
for (const int i : bake_items_.index_range()) {
mix_baked_data_item(eNodeSocketDatatype(bake_items_[i].socket_type),
output_values[i],
next_values[i],
mix_factor);
}
for (const int i : bake_items_.index_range()) {
const CPPType &type = *outputs_[i].type;
type.destruct(next_values[i]);
}
for (const int i : bake_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(output_values[i]));
}
}
std::optional<bake::BakeState> get_bake_state_from_inputs(
lf::Params &params, bke::bake::BakeDataBlockMap *data_block_map) const
{
Array<void *> input_values(bake_items_.size());
Array<bke::SocketValueVariant *> input_value_pointers(bake_items_.size());
for (const int i : bake_items_.index_range()) {
input_values[i] = params.try_get_input_data_ptr_or_request(i);
input_value_pointers[i] = params.try_get_input_data_ptr_or_request<bke::SocketValueVariant>(
i);
}
if (input_values.as_span().contains(nullptr)) {
if (input_value_pointers.as_span().contains(nullptr)) {
/* Wait for inputs to be computed. */
return std::nullopt;
}
Array<bke::SocketValueVariant> input_values(bake_items_.size());
for (const int i : bake_items_.index_range()) {
input_values[i] = std::move(*input_value_pointers[i]);
}
Array<std::unique_ptr<bake::BakeItem>> bake_items = bake::move_socket_values_to_bake_items(
input_values, bake_socket_config_, data_block_map);
@@ -430,11 +410,10 @@ class LazyFunctionForBakeNode final : public LazyFunction {
return bake_state;
}
void move_bake_state_to_values(bake::BakeState bake_state,
bke::bake::BakeDataBlockMap *data_block_map,
const Object &self_object,
const ComputeContext &compute_context,
Span<void *> r_output_values) const
Vector<SocketValueVariant> move_bake_state_to_values(bake::BakeState bake_state,
bke::bake::BakeDataBlockMap *data_block_map,
const Object &self_object,
const ComputeContext &compute_context) const
{
Vector<bake::BakeItem *> bake_items;
for (const NodeGeometryBakeItem &item : bake_items_) {
@@ -442,35 +421,26 @@ class LazyFunctionForBakeNode final : public LazyFunction {
item.identifier);
bake_items.append(bake_item ? bake_item->get() : nullptr);
}
bake::move_bake_items_to_socket_values(
bake_items,
bake_socket_config_,
data_block_map,
[&](const int i, const CPPType &type) {
return bake::move_bake_items_to_socket_values(
bake_items, bake_socket_config_, data_block_map, [&](const int i, const CPPType &type) {
return this->make_attribute_field(self_object, compute_context, bake_items_[i], type);
},
r_output_values);
});
}
void copy_bake_state_to_values(const bake::BakeStateRef &bake_state,
bke::bake::BakeDataBlockMap *data_block_map,
const Object &self_object,
const ComputeContext &compute_context,
Span<void *> r_output_values) const
Vector<SocketValueVariant> copy_bake_state_to_values(const bake::BakeStateRef &bake_state,
bke::bake::BakeDataBlockMap *data_block_map,
const Object &self_object,
const ComputeContext &compute_context) const
{
Vector<const bake::BakeItem *> bake_items;
for (const NodeGeometryBakeItem &item : bake_items_) {
const bake::BakeItem *const *bake_item = bake_state.items_by_id.lookup_ptr(item.identifier);
bake_items.append(bake_item ? *bake_item : nullptr);
}
bake::copy_bake_items_to_socket_values(
bake_items,
bake_socket_config_,
data_block_map,
[&](const int i, const CPPType &type) {
return bake::copy_bake_items_to_socket_values(
bake_items, bake_socket_config_, data_block_map, [&](const int i, const CPPType &type) {
return this->make_attribute_field(self_object, compute_context, bake_items_[i], type);
},
r_output_values);
});
}
std::shared_ptr<AttributeFieldInput> make_attribute_field(const Object &self_object,

View File

@@ -103,13 +103,13 @@ static std::shared_ptr<AttributeFieldInput> make_attribute_field(
std::move(attribute_name), type, std::move(socket_inspection_name));
}
static void move_simulation_state_to_values(const Span<NodeSimulationItem> node_simulation_items,
bke::bake::BakeState zone_state,
const Object &self_object,
const ComputeContext &compute_context,
const bNode &node,
bke::bake::BakeDataBlockMap *data_block_map,
Span<void *> r_output_values)
static Vector<SocketValueVariant> move_simulation_state_to_values(
const Span<NodeSimulationItem> node_simulation_items,
bke::bake::BakeState zone_state,
const Object &self_object,
const ComputeContext &compute_context,
const bNode &node,
bke::bake::BakeDataBlockMap *data_block_map)
{
const bke::bake::BakeSocketConfig config = make_bake_socket_config(node_simulation_items);
Vector<bke::bake::BakeItem *> bake_items;
@@ -119,24 +119,20 @@ static void move_simulation_state_to_values(const Span<NodeSimulationItem> node_
bake_items.append(bake_item ? bake_item->get() : nullptr);
}
bke::bake::move_bake_items_to_socket_values(
bake_items,
config,
data_block_map,
[&](const int i, const CPPType &type) {
return bke::bake::move_bake_items_to_socket_values(
bake_items, config, data_block_map, [&](const int i, const CPPType &type) {
return make_attribute_field(
self_object, compute_context, node, node_simulation_items[i], type);
},
r_output_values);
});
}
static void copy_simulation_state_to_values(const Span<NodeSimulationItem> node_simulation_items,
const bke::bake::BakeStateRef &zone_state,
const Object &self_object,
const ComputeContext &compute_context,
const bNode &node,
bke::bake::BakeDataBlockMap *data_block_map,
Span<void *> r_output_values)
static Vector<SocketValueVariant> copy_simulation_state_to_values(
const Span<NodeSimulationItem> node_simulation_items,
const bke::bake::BakeStateRef &zone_state,
const Object &self_object,
const ComputeContext &compute_context,
const bNode &node,
bke::bake::BakeDataBlockMap *data_block_map)
{
const bke::bake::BakeSocketConfig config = make_bake_socket_config(node_simulation_items);
Vector<const bke::bake::BakeItem *> bake_items;
@@ -146,20 +142,16 @@ static void copy_simulation_state_to_values(const Span<NodeSimulationItem> node_
bake_items.append(bake_item ? *bake_item : nullptr);
}
bke::bake::copy_bake_items_to_socket_values(
bake_items,
config,
data_block_map,
[&](const int i, const CPPType &type) {
return bke::bake::copy_bake_items_to_socket_values(
bake_items, config, data_block_map, [&](const int i, const CPPType &type) {
return make_attribute_field(
self_object, compute_context, node, node_simulation_items[i], type);
},
r_output_values);
});
}
static bke::bake::BakeState move_values_to_simulation_state(
const Span<NodeSimulationItem> node_simulation_items,
const Span<void *> input_values,
MutableSpan<SocketValueVariant> input_values,
bke::bake::BakeDataBlockMap *data_block_map)
{
const bke::bake::BakeSocketConfig config = make_bake_socket_config(node_simulation_items);
@@ -347,19 +339,15 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
bke::bake::BakeDataBlockMap *data_block_map,
const bke::bake::BakeStateRef &zone_state) const
{
Array<void *> outputs(simulation_items_.size());
Vector<SocketValueVariant> output_values = copy_simulation_state_to_values(
simulation_items_,
zone_state,
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map);
for (const int i : simulation_items_.index_range()) {
outputs[i] = params.get_output_data_ptr(i + 1);
}
copy_simulation_state_to_values(simulation_items_,
zone_state,
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map,
outputs);
for (const int i : simulation_items_.index_range()) {
params.output_set(i + 1);
params.set_output(i + 1, std::move(output_values[i]));
}
}
@@ -368,19 +356,15 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
bke::bake::BakeDataBlockMap *data_block_map,
bke::bake::BakeState zone_state) const
{
Array<void *> outputs(simulation_items_.size());
Vector<SocketValueVariant> output_values = move_simulation_state_to_values(
simulation_items_,
std::move(zone_state),
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map);
for (const int i : simulation_items_.index_range()) {
outputs[i] = params.get_output_data_ptr(i + 1);
}
move_simulation_state_to_values(simulation_items_,
std::move(zone_state),
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map,
outputs);
for (const int i : simulation_items_.index_range()) {
params.output_set(i + 1);
params.set_output(i + 1, std::move(output_values[i]));
}
}
@@ -388,14 +372,19 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
const GeoNodesUserData &user_data,
bke::bake::BakeDataBlockMap *data_block_map) const
{
Array<void *> input_values(inputs_.size());
Array<SocketValueVariant *> input_value_pointers(inputs_.size());
for (const int i : inputs_.index_range()) {
input_values[i] = params.try_get_input_data_ptr_or_request(i);
input_value_pointers[i] = params.try_get_input_data_ptr_or_request<SocketValueVariant>(i);
}
if (input_values.as_span().contains(nullptr)) {
if (input_value_pointers.as_span().contains(nullptr)) {
/* Wait for inputs to be computed. */
return;
}
Array<SocketValueVariant> input_values(inputs_.size());
for (const int i : inputs_.index_range()) {
input_values[i] = std::move(*input_value_pointers[i]);
}
/* Instead of outputting the initial values directly, convert them to a simulation state and
* then back. This ensures that some geometry processing happens on the data consistently (e.g.
* removing anonymous attributes). */
@@ -639,19 +628,15 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
bke::bake::BakeDataBlockMap *data_block_map,
const bke::bake::BakeStateRef &state) const
{
Array<void *> output_values(simulation_items_.size());
Vector<SocketValueVariant> output_values = copy_simulation_state_to_values(
simulation_items_,
state,
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map);
for (const int i : simulation_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
copy_simulation_state_to_values(simulation_items_,
state,
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map,
output_values);
for (const int i : simulation_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(output_values[i]));
}
}
@@ -663,46 +648,19 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
const bke::bake::BakeStateRef &next_state,
const float mix_factor) const
{
Array<void *> output_values(simulation_items_.size());
for (const int i : simulation_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
copy_simulation_state_to_values(simulation_items_,
prev_state,
self_object,
compute_context,
node_,
data_block_map,
output_values);
Array<void *> next_values(simulation_items_.size());
LinearAllocator<> allocator;
for (const int i : simulation_items_.index_range()) {
const CPPType &type = *outputs_[i].type;
next_values[i] = allocator.allocate(type);
}
copy_simulation_state_to_values(simulation_items_,
next_state,
self_object,
compute_context,
node_,
data_block_map,
next_values);
Vector<SocketValueVariant> output_values = copy_simulation_state_to_values(
simulation_items_, prev_state, self_object, compute_context, node_, data_block_map);
Vector<SocketValueVariant> next_values = copy_simulation_state_to_values(
simulation_items_, next_state, self_object, compute_context, node_, data_block_map);
for (const int i : simulation_items_.index_range()) {
mix_baked_data_item(eNodeSocketDatatype(simulation_items_[i].socket_type),
output_values[i],
next_values[i],
mix_factor);
}
for (const int i : simulation_items_.index_range()) {
const CPPType &type = *outputs_[i].type;
type.destruct(next_values[i]);
}
for (const int i : simulation_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(output_values[i]));
}
}
@@ -716,20 +674,15 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
/* Wait for inputs to be computed. */
return;
}
Array<void *> output_values(simulation_items_.size());
Vector<SocketValueVariant> output_values = move_simulation_state_to_values(
simulation_items_,
std::move(*bake_state),
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map);
for (const int i : simulation_items_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
move_simulation_state_to_values(simulation_items_,
std::move(*bake_state),
*user_data.call_data->self_object(),
*user_data.compute_context,
node_,
data_block_map,
output_values);
for (const int i : simulation_items_.index_range()) {
params.output_set(i);
params.set_output(i, std::move(output_values[i]));
}
}
@@ -764,15 +717,21 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
{
/* Choose which set of input parameters to use. The others are ignored. */
const int params_offset = skip ? skip_inputs_offset_ : solve_inputs_offset_;
Array<void *> input_values(simulation_items_.size());
Array<SocketValueVariant *> input_value_pointers(simulation_items_.size());
for (const int i : simulation_items_.index_range()) {
input_values[i] = params.try_get_input_data_ptr_or_request(i + params_offset);
input_value_pointers[i] = params.try_get_input_data_ptr_or_request<SocketValueVariant>(
i + params_offset);
}
if (input_values.as_span().contains(nullptr)) {
if (input_value_pointers.as_span().contains(nullptr)) {
/* Wait for inputs to be computed. */
return std::nullopt;
}
Array<SocketValueVariant> input_values(simulation_items_.size());
for (const int i : simulation_items_.index_range()) {
input_values[i] = std::move(*input_value_pointers[i]);
}
return move_values_to_simulation_state(simulation_items_, input_values, data_block_map);
}
};
@@ -979,14 +938,14 @@ std::unique_ptr<LazyFunction> get_simulation_output_lazy_function(
}
void mix_baked_data_item(const eNodeSocketDatatype socket_type,
void *prev,
const void *next,
SocketValueVariant &prev,
const SocketValueVariant &next,
const float factor)
{
switch (socket_type) {
case SOCK_GEOMETRY: {
GeometrySet &prev_geo = *static_cast<GeometrySet *>(prev);
const GeometrySet &next_geo = *static_cast<const GeometrySet *>(next);
GeometrySet &prev_geo = *prev.get_single_ptr().get<GeometrySet>();
const GeometrySet &next_geo = *next.get_single_ptr().get<GeometrySet>();
prev_geo = geometry::mix_geometries(std::move(prev_geo), next_geo, factor);
break;
}
@@ -998,20 +957,18 @@ void mix_baked_data_item(const eNodeSocketDatatype socket_type,
case SOCK_RGBA:
case SOCK_MATRIX: {
const CPPType &type = *bke::socket_type_to_geo_nodes_base_cpp_type(socket_type);
SocketValueVariant prev_value_variant = *static_cast<const SocketValueVariant *>(prev);
SocketValueVariant next_value_variant = *static_cast<const SocketValueVariant *>(next);
if (prev_value_variant.is_context_dependent_field() ||
next_value_variant.is_context_dependent_field())
{
if (prev.is_context_dependent_field() || next.is_context_dependent_field()) {
/* Fields are evaluated on geometries and are mixed there. */
break;
}
prev_value_variant.convert_to_single();
next_value_variant.convert_to_single();
prev.convert_to_single();
void *prev_value = prev_value_variant.get_single_ptr().get();
const void *next_value = next_value_variant.get_single_ptr().get();
SocketValueVariant next_copy = next;
next_copy.convert_to_single();
void *prev_value = prev.get_single_ptr().get();
const void *next_value = next_copy.get_single_ptr().get();
bke::attribute_math::convert_to_static_type(type, [&](auto dummy) {
using T = decltype(dummy);