Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-11-23 16:47:25 +0300
committerJacques Lucke <jacques@blender.org>2021-11-23 16:49:26 +0300
commit47276b84701727c2f187c77f1ec502b4ca4963bd (patch)
treeac6e6fced7908dbaa984cfe686b2e3a080b99fc7 /source/blender/nodes
parent0bedd5d14f6d61a6a4a96cc7f88484b0dc46f752 (diff)
Geometry Nodes: reduce overhead when processing single values
Currently the geometry nodes evaluator always stores a field for every type that supports it, even if it is just a single value. This results in a lot of overhead when there are many sockets that just contain a single value, which is often the case. This introduces a new `ValueOrField<T>` type that is used by the geometry nodes evaluator. Now a field will only be created when it is actually necessary. See D13307 for more details. In extrem cases this can speed up the evaluation 2-3x (those cases are probably never hit in practice though, but it's good to get rid of unnecessary overhead nevertheless). Differential Revision: https://developer.blender.org/D13307
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/NOD_geometry_exec.hh43
-rw-r--r--source/blender/nodes/intern/geometry_nodes_eval_log.cc46
-rw-r--r--source/blender/nodes/intern/node_socket.cc28
3 files changed, 72 insertions, 45 deletions
diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh
index 700f32ee414..6b6e8a89240 100644
--- a/source/blender/nodes/NOD_geometry_exec.hh
+++ b/source/blender/nodes/NOD_geometry_exec.hh
@@ -59,6 +59,7 @@ using fn::GVArray;
using fn::GVArray_GSpan;
using fn::GVMutableArray;
using fn::GVMutableArray_GSpan;
+using fn::ValueOrField;
using geometry_nodes_eval_log::NodeWarningType;
/**
@@ -129,7 +130,7 @@ class GeoNodeExecParams {
}
template<typename T>
- static inline constexpr bool is_stored_as_field_v = std::is_same_v<T, float> ||
+ static inline constexpr bool is_field_base_type_v = std::is_same_v<T, float> ||
std::is_same_v<T, int> ||
std::is_same_v<T, bool> ||
std::is_same_v<T, ColorGeometry4f> ||
@@ -157,9 +158,15 @@ class GeoNodeExecParams {
*/
template<typename T> T extract_input(StringRef identifier)
{
- if constexpr (is_stored_as_field_v<T>) {
- Field<T> field = this->extract_input<Field<T>>(identifier);
- return fn::evaluate_constant_field(field);
+ if constexpr (is_field_base_type_v<T>) {
+ ValueOrField<T> value_or_field = this->extract_input<ValueOrField<T>>(identifier);
+ return value_or_field.as_value();
+ }
+ else if constexpr (fn::is_field_v<T>) {
+ using BaseType = typename T::base_type;
+ ValueOrField<BaseType> value_or_field = this->extract_input<ValueOrField<BaseType>>(
+ identifier);
+ return value_or_field.as_field();
}
else {
#ifdef DEBUG
@@ -186,9 +193,9 @@ class GeoNodeExecParams {
Vector<GMutablePointer> gvalues = provider_->extract_multi_input(identifier);
Vector<T> values;
for (GMutablePointer gvalue : gvalues) {
- if constexpr (is_stored_as_field_v<T>) {
- const Field<T> field = gvalue.relocate_out<Field<T>>();
- values.append(fn::evaluate_constant_field(field));
+ if constexpr (is_field_base_type_v<T>) {
+ const ValueOrField<T> value_or_field = gvalue.relocate_out<ValueOrField<T>>();
+ values.append(value_or_field.as_value());
}
else {
values.append(gvalue.relocate_out<T>());
@@ -200,11 +207,16 @@ class GeoNodeExecParams {
/**
* Get the input value for the input socket with the given identifier.
*/
- template<typename T> const T get_input(StringRef identifier) const
+ template<typename T> T get_input(StringRef identifier) const
{
- if constexpr (is_stored_as_field_v<T>) {
- const Field<T> &field = this->get_input<Field<T>>(identifier);
- return fn::evaluate_constant_field(field);
+ if constexpr (is_field_base_type_v<T>) {
+ ValueOrField<T> value_or_field = this->get_input<ValueOrField<T>>(identifier);
+ return value_or_field.as_value();
+ }
+ else if constexpr (fn::is_field_v<T>) {
+ using BaseType = typename T::base_type;
+ ValueOrField<BaseType> value_or_field = this->get_input<ValueOrField<BaseType>>(identifier);
+ return value_or_field.as_field();
}
else {
#ifdef DEBUG
@@ -226,9 +238,12 @@ class GeoNodeExecParams {
template<typename T> void set_output(StringRef identifier, T &&value)
{
using StoredT = std::decay_t<T>;
- if constexpr (is_stored_as_field_v<StoredT>) {
- this->set_output<Field<StoredT>>(identifier,
- fn::make_constant_field<StoredT>(std::forward<T>(value)));
+ if constexpr (is_field_base_type_v<StoredT>) {
+ this->set_output(identifier, ValueOrField<StoredT>(std::forward<T>(value)));
+ }
+ else if constexpr (fn::is_field_v<StoredT>) {
+ using BaseType = typename StoredT::base_type;
+ this->set_output(identifier, ValueOrField<BaseType>(std::forward<T>(value)));
}
else {
const CPPType &type = CPPType::get<StoredT>();
diff --git a/source/blender/nodes/intern/geometry_nodes_eval_log.cc b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
index ddd3c991518..782ab43336c 100644
--- a/source/blender/nodes/intern/geometry_nodes_eval_log.cc
+++ b/source/blender/nodes/intern/geometry_nodes_eval_log.cc
@@ -31,6 +31,7 @@ using fn::CPPType;
using fn::FieldCPPType;
using fn::FieldInput;
using fn::GField;
+using fn::ValueOrFieldCPPType;
ModifierLog::ModifierLog(GeoLogger &logger)
: input_geometry_log_(std::move(logger.input_geometry_log_)),
@@ -417,25 +418,38 @@ void LocalGeoLogger::log_value_for_sockets(Span<DSocket> sockets, GPointer value
geometry_set, log_full_geometry);
values_.append({copied_sockets, std::move(value_log)});
}
- else if (const FieldCPPType *field_type = dynamic_cast<const FieldCPPType *>(&type)) {
- GField field = field_type->get_gfield(value.get());
- bool log_full_field = false;
- if (!field.node().depends_on_input()) {
- /* Always log constant fields so that their value can be shown in socket inspection.
- * In the future we can also evaluate the field here and only store the value. */
- log_full_field = true;
- }
- if (!log_full_field) {
- for (const DSocket &socket : sockets) {
- if (main_logger_->log_full_sockets_.contains(socket)) {
- log_full_field = true;
- break;
+ else if (const ValueOrFieldCPPType *value_or_field_type =
+ dynamic_cast<const ValueOrFieldCPPType *>(&type)) {
+ const void *value_or_field = value.get();
+ if (value_or_field_type->is_field(value_or_field)) {
+ GField field = *value_or_field_type->get_field_ptr(value_or_field);
+ bool log_full_field = false;
+ if (!field.node().depends_on_input()) {
+ /* Always log constant fields so that their value can be shown in socket inspection.
+ * In the future we can also evaluate the field here and only store the value. */
+ log_full_field = true;
+ }
+ if (!log_full_field) {
+ for (const DSocket &socket : sockets) {
+ if (main_logger_->log_full_sockets_.contains(socket)) {
+ log_full_field = true;
+ break;
+ }
}
}
+ destruct_ptr<GFieldValueLog> value_log = allocator_->construct<GFieldValueLog>(
+ std::move(field), log_full_field);
+ values_.append({copied_sockets, std::move(value_log)});
+ }
+ else {
+ const CPPType &base_type = value_or_field_type->base_type();
+ const void *value = value_or_field_type->get_value_ptr(value_or_field);
+ void *buffer = allocator_->allocate(base_type.size(), base_type.alignment());
+ base_type.copy_construct(value, buffer);
+ destruct_ptr<GenericValueLog> value_log = allocator_->construct<GenericValueLog>(
+ GMutablePointer{base_type, buffer});
+ values_.append({copied_sockets, std::move(value_log)});
}
- destruct_ptr<GFieldValueLog> value_log = allocator_->construct<GFieldValueLog>(
- std::move(field), log_full_field);
- values_.append({copied_sockets, std::move(value_log)});
}
else {
void *buffer = allocator_->allocate(type.size(), type.alignment());
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 200e4120346..68e8f6421bd 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -51,6 +51,7 @@
#include "FN_field.hh"
using namespace blender;
+using blender::fn::ValueOrField;
using blender::nodes::SocketDeclarationPtr;
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
@@ -701,11 +702,11 @@ static bNodeSocketType *make_socket_type_bool()
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(bool *)r_value = ((bNodeSocketValueBoolean *)socket.default_value)->value;
};
- socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<blender::fn::Field<bool>>();
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<bool>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
bool value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<bool>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<bool>(value);
};
return socktype;
}
@@ -717,11 +718,11 @@ static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(float *)r_value = ((bNodeSocketValueFloat *)socket.default_value)->value;
};
- socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<blender::fn::Field<float>>();
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<float>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
float value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<float>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<float>(value);
};
return socktype;
}
@@ -733,11 +734,11 @@ static bNodeSocketType *make_socket_type_int(PropertySubType subtype)
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(int *)r_value = ((bNodeSocketValueInt *)socket.default_value)->value;
};
- socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<blender::fn::Field<int>>();
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<int>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
int value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<int>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<int>(value);
};
return socktype;
}
@@ -749,12 +750,11 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
*(blender::float3 *)r_value = ((bNodeSocketValueVector *)socket.default_value)->value;
};
- socktype->geometry_nodes_cpp_type =
- &blender::fn::CPPType::get<blender::fn::Field<blender::float3>>();
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<blender::float3>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::float3 value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<blender::float3>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<blender::float3>(value);
};
return socktype;
}
@@ -767,12 +767,11 @@ static bNodeSocketType *make_socket_type_rgba()
*(blender::ColorGeometry4f *)r_value = ((bNodeSocketValueRGBA *)socket.default_value)->value;
};
socktype->geometry_nodes_cpp_type =
- &blender::fn::CPPType::get<blender::fn::Field<blender::ColorGeometry4f>>();
+ &blender::fn::CPPType::get<ValueOrField<blender::ColorGeometry4f>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
blender::ColorGeometry4f value;
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value)
- blender::fn::Field<blender::ColorGeometry4f>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<blender::ColorGeometry4f>(value);
};
return socktype;
}
@@ -784,13 +783,12 @@ static bNodeSocketType *make_socket_type_string()
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
new (r_value) std::string(((bNodeSocketValueString *)socket.default_value)->value);
};
- socktype->geometry_nodes_cpp_type =
- &blender::fn::CPPType::get<blender::fn::Field<std::string>>();
+ socktype->geometry_nodes_cpp_type = &blender::fn::CPPType::get<ValueOrField<std::string>>();
socktype->get_geometry_nodes_cpp_value = [](const bNodeSocket &socket, void *r_value) {
std::string value;
value.~basic_string();
socket.typeinfo->get_base_cpp_value(socket, &value);
- new (r_value) blender::fn::Field<std::string>(blender::fn::make_constant_field(value));
+ new (r_value) ValueOrField<std::string>(value);
};
return socktype;
}