Geometry Nodes: don't log full fields when not necessary
Previously, the field on every socket was logged for later use. This had two main negative consequences: * Increased memory usage, because the fields may contain a lot of data under some circumstances (e.g. a Ray Cast field contains the target geometry). * Decreased performance, because anonymous attributes could not be removed from geometry automatically, because there were still fields that referenced them. Now most fields are not logged anymore. Only those that are viewed by a spreadsheet and constant fields. The required inputs of a field are still logged in string form to keep socket inspection working.
This commit is contained in:
parent
41a4c62c31
commit
d20fa6c4d4
|
@ -854,60 +854,7 @@ static void create_inspection_string_for_generic_value(const geo_log::GenericVal
|
|||
|
||||
const GPointer value = value_log.value();
|
||||
const CPPType &type = *value.type();
|
||||
if (const FieldCPPType *field_type = dynamic_cast<const FieldCPPType *>(&type)) {
|
||||
const CPPType &base_type = field_type->field_type();
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(base_type, buffer);
|
||||
const GField &field = field_type->get_gfield(value.get());
|
||||
if (field.node().depends_on_input()) {
|
||||
if (base_type.is<int>()) {
|
||||
ss << TIP_("Integer Field");
|
||||
}
|
||||
else if (base_type.is<float>()) {
|
||||
ss << TIP_("Float Field");
|
||||
}
|
||||
else if (base_type.is<blender::float3>()) {
|
||||
ss << TIP_("Vector Field");
|
||||
}
|
||||
else if (base_type.is<bool>()) {
|
||||
ss << TIP_("Boolean Field");
|
||||
}
|
||||
else if (base_type.is<std::string>()) {
|
||||
ss << TIP_("String Field");
|
||||
}
|
||||
ss << TIP_(" based on:\n");
|
||||
|
||||
/* Use vector set to deduplicate inputs. */
|
||||
VectorSet<std::reference_wrapper<const FieldInput>> field_inputs;
|
||||
field.node().foreach_field_input(
|
||||
[&](const FieldInput &field_input) { field_inputs.add(field_input); });
|
||||
for (const FieldInput &field_input : field_inputs) {
|
||||
ss << "\u2022 " << field_input.socket_inspection_name();
|
||||
if (field_input != field_inputs.as_span().last().get()) {
|
||||
ss << ".\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
blender::fn::evaluate_constant_field(field, buffer);
|
||||
if (base_type.is<int>()) {
|
||||
ss << *(int *)buffer << TIP_(" (Integer)");
|
||||
}
|
||||
else if (base_type.is<float>()) {
|
||||
ss << *(float *)buffer << TIP_(" (Float)");
|
||||
}
|
||||
else if (base_type.is<blender::float3>()) {
|
||||
ss << *(blender::float3 *)buffer << TIP_(" (Vector)");
|
||||
}
|
||||
else if (base_type.is<bool>()) {
|
||||
ss << ((*(bool *)buffer) ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
|
||||
}
|
||||
else if (base_type.is<std::string>()) {
|
||||
ss << *(std::string *)buffer << TIP_(" (String)");
|
||||
}
|
||||
base_type.destruct(buffer);
|
||||
}
|
||||
}
|
||||
else if (type.is<Object *>()) {
|
||||
if (type.is<Object *>()) {
|
||||
id_to_inspection_string((ID *)*value.get<Object *>(), ID_OB);
|
||||
}
|
||||
else if (type.is<Material *>()) {
|
||||
|
@ -924,6 +871,71 @@ static void create_inspection_string_for_generic_value(const geo_log::GenericVal
|
|||
}
|
||||
}
|
||||
|
||||
static void create_inspection_string_for_gfield(const geo_log::GFieldValueLog &value_log,
|
||||
std::stringstream &ss)
|
||||
{
|
||||
const CPPType &type = value_log.type();
|
||||
const GField &field = value_log.field();
|
||||
const Span<std::string> input_tooltips = value_log.input_tooltips();
|
||||
|
||||
if (input_tooltips.is_empty()) {
|
||||
if (field) {
|
||||
BUFFER_FOR_CPP_TYPE_VALUE(type, buffer);
|
||||
blender::fn::evaluate_constant_field(field, buffer);
|
||||
if (type.is<int>()) {
|
||||
ss << *(int *)buffer << TIP_(" (Integer)");
|
||||
}
|
||||
else if (type.is<float>()) {
|
||||
ss << *(float *)buffer << TIP_(" (Float)");
|
||||
}
|
||||
else if (type.is<blender::float3>()) {
|
||||
ss << *(blender::float3 *)buffer << TIP_(" (Vector)");
|
||||
}
|
||||
else if (type.is<bool>()) {
|
||||
ss << ((*(bool *)buffer) ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
|
||||
}
|
||||
else if (type.is<std::string>()) {
|
||||
ss << *(std::string *)buffer << TIP_(" (String)");
|
||||
}
|
||||
type.destruct(buffer);
|
||||
}
|
||||
else {
|
||||
/* Constant values should always be logged. */
|
||||
BLI_assert_unreachable();
|
||||
ss << "Value has not been logged";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (type.is<int>()) {
|
||||
ss << TIP_("Integer Field");
|
||||
}
|
||||
else if (type.is<float>()) {
|
||||
ss << TIP_("Float Field");
|
||||
}
|
||||
else if (type.is<blender::float3>()) {
|
||||
ss << TIP_("Vector Field");
|
||||
}
|
||||
else if (type.is<bool>()) {
|
||||
ss << TIP_("Boolean Field");
|
||||
}
|
||||
else if (type.is<std::string>()) {
|
||||
ss << TIP_("String Field");
|
||||
}
|
||||
else if (type.is<blender::ColorGeometry4f>()) {
|
||||
ss << TIP_("Color Field");
|
||||
}
|
||||
ss << TIP_(" based on:\n");
|
||||
|
||||
for (const int i : input_tooltips.index_range()) {
|
||||
const blender::StringRef tooltip = input_tooltips[i];
|
||||
ss << "\u2022 " << tooltip;
|
||||
if (i < input_tooltips.size() - 1) {
|
||||
ss << ".\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void create_inspection_string_for_geometry(const geo_log::GeometryValueLog &value_log,
|
||||
std::stringstream &ss)
|
||||
{
|
||||
|
@ -1015,6 +1027,10 @@ static std::optional<std::string> create_socket_inspection_string(bContext *C,
|
|||
dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
|
||||
create_inspection_string_for_generic_value(*generic_value_log, ss);
|
||||
}
|
||||
if (const geo_log::GFieldValueLog *gfield_value_log =
|
||||
dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) {
|
||||
create_inspection_string_for_gfield(*gfield_value_log, ss);
|
||||
}
|
||||
else if (const geo_log::GeometryValueLog *geo_value_log =
|
||||
dynamic_cast<const geo_log::GeometryValueLog *>(value_log)) {
|
||||
create_inspection_string_for_geometry(*geo_value_log, ss);
|
||||
|
|
|
@ -574,14 +574,12 @@ static void find_fields_to_evaluate(const SpaceSpreadsheet *sspreadsheet,
|
|||
if (value_log == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (const geo_log::GenericValueLog *generic_value_log =
|
||||
dynamic_cast<const geo_log::GenericValueLog *>(value_log)) {
|
||||
const fn::GPointer value = generic_value_log->value();
|
||||
if (!dynamic_cast<const fn::FieldCPPType *>(value.type())) {
|
||||
continue;
|
||||
if (const geo_log::GFieldValueLog *field_value_log =
|
||||
dynamic_cast<const geo_log::GFieldValueLog *>(value_log)) {
|
||||
const GField &field = field_value_log->field();
|
||||
if (field) {
|
||||
r_fields.add("Viewer", std::move(field));
|
||||
}
|
||||
GField field = *(const GField *)value.get();
|
||||
r_fields.add("Viewer", std::move(field));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,31 @@ class GenericValueLog : public ValueLog {
|
|||
}
|
||||
};
|
||||
|
||||
class GFieldValueLog : public ValueLog {
|
||||
private:
|
||||
fn::GField field_;
|
||||
const fn::CPPType &type_;
|
||||
Vector<std::string> input_tooltips_;
|
||||
|
||||
public:
|
||||
GFieldValueLog(fn::GField field, bool log_full_field);
|
||||
|
||||
const fn::GField &field() const
|
||||
{
|
||||
return field_;
|
||||
}
|
||||
|
||||
Span<std::string> input_tooltips() const
|
||||
{
|
||||
return input_tooltips_;
|
||||
}
|
||||
|
||||
const fn::CPPType &type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
};
|
||||
|
||||
struct GeometryAttributeInfo {
|
||||
std::string name;
|
||||
AttributeDomain domain;
|
||||
|
|
|
@ -21,9 +21,16 @@
|
|||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "FN_field_cpp_type.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
namespace blender::nodes::geometry_nodes_eval_log {
|
||||
|
||||
using fn::CPPType;
|
||||
using fn::FieldCPPType;
|
||||
using fn::FieldInput;
|
||||
using fn::GField;
|
||||
|
||||
ModifierLog::ModifierLog(GeoLogger &logger)
|
||||
: input_geometry_log_(std::move(logger.input_geometry_log_)),
|
||||
|
@ -168,6 +175,20 @@ const SocketLog *NodeLog::lookup_socket_log(const bNode &node, const bNodeSocket
|
|||
return this->lookup_socket_log((eNodeSocketInOut)socket.in_out, index);
|
||||
}
|
||||
|
||||
GFieldValueLog::GFieldValueLog(fn::GField field, bool log_full_field) : type_(field.cpp_type())
|
||||
{
|
||||
VectorSet<std::reference_wrapper<const FieldInput>> field_inputs;
|
||||
field.node().foreach_field_input(
|
||||
[&](const FieldInput &field_input) { field_inputs.add(field_input); });
|
||||
for (const FieldInput &field_input : field_inputs) {
|
||||
input_tooltips_.append(field_input.socket_inspection_name());
|
||||
}
|
||||
|
||||
if (log_full_field) {
|
||||
field_ = std::move(field);
|
||||
}
|
||||
}
|
||||
|
||||
GeometryValueLog::GeometryValueLog(const GeometrySet &geometry_set, bool log_full_geometry)
|
||||
{
|
||||
static std::array all_component_types = {GEO_COMPONENT_TYPE_CURVE,
|
||||
|
@ -382,6 +403,26 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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());
|
||||
type.copy_construct(value.get(), buffer);
|
||||
|
|
Loading…
Reference in New Issue