[Bf-blender-cvs] [ceb9e7d71e4] temp-geometry-nodes-fields-prototype: initial commit
Jacques Lucke
noreply at git.blender.org
Wed Jul 28 14:14:18 CEST 2021
Commit: ceb9e7d71e4786e747775a51bfee0b3b4efe21ef
Author: Jacques Lucke
Date: Fri Jul 9 17:48:51 2021 +0200
Branches: temp-geometry-nodes-fields-prototype
https://developer.blender.org/rBceb9e7d71e4786e747775a51bfee0b3b4efe21ef
initial commit
===================================================================
A source/blender/blenkernel/BKE_field.hh
M source/blender/blenlib/BLI_hash.hh
M source/blender/blenlib/tests/BLI_map_test.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_field.hh b/source/blender/blenkernel/BKE_field.hh
new file mode 100644
index 00000000000..f674ef78957
--- /dev/null
+++ b/source/blender/blenkernel/BKE_field.hh
@@ -0,0 +1,309 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BLI_function_ref.hh"
+#include "BLI_map.hh"
+#include "BLI_vector.hh"
+#include "BLI_virtual_array.hh"
+
+#include "FN_cpp_type.hh"
+#include "FN_multi_function.hh"
+
+namespace blender::bke {
+
+using fn::CPPType;
+using fn::GVArray;
+using fn::GVArrayPtr;
+using fn::MultiFunction;
+
+class FieldInputKey {
+ public:
+ virtual ~FieldInputKey() = default;
+ virtual uint64_t hash() const = 0;
+
+ friend bool operator==(const FieldInputKey &a, const FieldInputKey &b)
+ {
+ return a.is_same_as(b);
+ }
+
+ private:
+ virtual bool is_same_as(const FieldInputKey &other) const
+ {
+ return false;
+ }
+};
+
+class FieldInputValue {
+ public:
+ virtual ~FieldInputValue() = default;
+};
+
+class AttributeFieldInputKey : public FieldInputKey {
+ private:
+ std::string name_;
+ const CPPType *type_;
+
+ public:
+ AttributeFieldInputKey(std::string name, const CPPType &type)
+ : name_(std::move(name)), type_(&type)
+ {
+ }
+
+ uint64_t hash() const override
+ {
+ return get_default_hash_2(name_, type_);
+ }
+
+ private:
+ bool is_same_as(const FieldInputKey &other) const
+ {
+ if (const AttributeFieldInputKey *other_typed = dynamic_cast<const AttributeFieldInputKey *>(
+ &other)) {
+ return other_typed->type_ == type_ && other_typed->name_ == name_;
+ }
+ return false;
+ }
+};
+
+template<typename T> class VArrayFieldInputValue : public FieldInputValue {
+ private:
+ const VArray<T> *varray_;
+
+ public:
+ VArrayFieldInputValue(const VArray<T> &varray) : varray_(varray)
+ {
+ }
+
+ const VArray<T> &varray() const
+ {
+ return *varray_;
+ }
+};
+
+class FieldInputs {
+ private:
+ using InputMap = Map<std::reference_wrapper<const FieldInputKey>, const FieldInputValue *>;
+ InputMap inputs_;
+
+ friend class GField;
+
+ public:
+ InputMap::KeyIterator begin() const
+ {
+ return inputs_.keys().begin();
+ }
+
+ InputMap::KeyIterator end() const
+ {
+ return inputs_.keys().end();
+ }
+
+ void set_input(const FieldInputKey &key, const FieldInputValue &value)
+ {
+ *inputs_.lookup_ptr(key) = &value;
+ }
+
+ const FieldInputValue *get(const FieldInputKey &key) const
+ {
+ return inputs_.lookup_default(key, nullptr);
+ }
+
+ template<typename ValueT> const ValueT *get(const FieldInputKey &key) const
+ {
+ return dynamic_cast<const ValueT *>(this->get(key));
+ }
+};
+
+template<typename T> class FieldOutput {
+ private:
+ VArray<T> *varray_ = nullptr;
+ VArrayPtr<T> varray_owned_;
+
+ public:
+ FieldOutput(const VArray<T> &varray) : varray_(&varray)
+ {
+ }
+
+ FieldOutput(VArrayPtr<T> varray) : varray_(varray.get()), varray_owned_(std::move(varray))
+ {
+ }
+
+ VArrayPtr<T> &varray_owned()
+ {
+ return varray_owned_;
+ }
+
+ const VArray<T> &varray_ref() const
+ {
+ return *varray_;
+ }
+};
+
+class GFieldOutput {
+ private:
+ const GVArray *varray_;
+ GVArrayPtr varray_owned_;
+
+ public:
+ GFieldOutput(const GVArray &varray) : varray_(&varray)
+ {
+ }
+
+ GFieldOutput(GVArrayPtr varray) : varray_(varray.get()), varray_owned_(std::move(varray))
+ {
+ }
+
+ const GVArray &varray_ref() const
+ {
+ return *varray_;
+ }
+};
+
+class GField {
+ public:
+ virtual ~GField() = default;
+
+ FieldInputs prepare_inputs() const
+ {
+ FieldInputs inputs;
+ this->foreach_input_key([&](const FieldInputKey &key) { inputs.inputs_.add(key, nullptr); });
+ return inputs;
+ }
+
+ virtual void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const
+ {
+ UNUSED_VARS(callback);
+ }
+
+ virtual const CPPType &output_type() const = 0;
+
+ virtual GFieldOutput evaluate_generic(IndexMask mask, const FieldInputs &inputs) const = 0;
+};
+
+template<typename T> class Field : public GField {
+ public:
+ virtual FieldOutput<T> evaluate(IndexMask mask, const FieldInputs &inputs) const = 0;
+
+ GFieldOutput evaluate_generic(IndexMask mask, const FieldInputs &inputs) const override
+ {
+ FieldOutput<T> output = this->evaluate(mask, inputs);
+ if (output.varray_owned()) {
+ return std::make_unique<fn::GVArray_For_OwnedVArray>(std::move(output.varray_owned()));
+ }
+ return std::make_unique<fn::GVArray_For_VArray>(output.varray_ref());
+ }
+
+ const CPPType &output_type() const override
+ {
+ return CPPType::get<T>();
+ }
+};
+
+template<typename T> class ConstantField : public Field<T> {
+ private:
+ T value_;
+
+ public:
+ ConstantField(T value) : value_(std::move(value))
+ {
+ }
+
+ FieldOutput<T> evaluate(IndexMask mask, const FieldInputs &inputs) const
+ {
+ return std::make_unique<VArray_For_Single<T>>(value_, mask.min_array_size());
+ }
+};
+
+template<typename T, typename KeyT> class VArrayField : public Field<T> {
+ private:
+ T default_value_;
+ KeyT key_;
+
+ public:
+ template<typename... Args>
+ VArrayField(T default_value, Args &&... args)
+ : default_value_(std::move(default_value)), key_(std::forward<Args>(args)...)
+ {
+ }
+
+ void foreach_input_key(FunctionRef<void(const FieldInputKey &key)> callback) const
+ {
+ callback(key_);
+ }
+
+ FieldOutput<T> evaluate(IndexMask mask, const FieldInputs &inputs) const
+ {
+ const VArrayFieldInputValue<T> *input = inputs.<VArrayFieldInputValue<T>>(key_);
+ if (input == nullptr) {
+ return std::make_unique<VArray_For_Single<T>>(default_value_, mask.min_array_size());
+ }
+ return input->varray();
+ }
+};
+
+template<typename T> class MultiFunctionField : public Field<T> {
+ private:
+ Vector<std::shared_ptr<GField>> input_fields_;
+ const MultiFunction *fn_;
+ const int output_param_index_;
+
+ public:
+ MultiFunctionField(Vector<std::shared_ptr<GField>> input_fields,
+ const MultiFunction &fn,
+ const int output_param_index)
+ : input_fields_(std::move(input_fields)), fn_(&fn), output_param_index_(output_param_index)
+ {
+ }
+
+ FieldOutput<T> evaluate(IndexMask mask, const FieldInputs &inputs) const
+ {
+ fn::MFParamsBuilder params{*fn, mask.min_array_size()};
+ fn::MFContextBuilder context;
+
+ ResourceScope &scope = params.resource_scope();
+
+ const int input_index = 0;
+ for (const int param_index : fn_->param_indices()) {
+ fn::MFParamType param_type = fn_->param_type(param_index);
+ switch (param_type.category()) {
+ case fn::MFParamType::SingleInput: {
+ const GField &field = *input_fields_[input_index];
+ input_index++;
+ }
+ case fn::MFParamType::SingleOutput: {
+ if (param_index == output_param_index_) {
+ }
+ else {
+ }
+ }
+ case fn::MFParamType::SingleMutable:
+ case fn::MFParamType::VectorInput:
+ case fn::MFParamType::VectorMutable:
+ case fn::MFParamType::VectorOutput:
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+ }
+};
+
+} // namespace blender::bke
diff --git a/source/blender/blenlib/BLI_hash.hh b/source/blender/blenlib/BLI_hash.hh
index fbed321534c..c19b94a4ebf 100644
--- a/source/blender/blenlib/BLI_hash.hh
+++ b/source/blender/blenlib/BLI_hash.hh
@@ -250,6 +250,13 @@ template<typename T> struct DefaultHash<std::unique_ptr<T>> {
}
};
+template<typename T> struct DefaultHash<std::reference_wrapper<T>> {
+ uint64_t operator()(const std::reference_wrapper<T> &value) const
+ {
+ return get_default_hash(value.get());
+ }
+};
+
template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> {
uint64_t operator()(const std::pair<T1, T2> &value) const
{
diff --git a/source/blender/blenlib/tests/BLI_map_test.cc b/source/blender/blenlib/tests/BLI_map_test.cc
index 679a10e9ce0..7c6eaac0c55 100644
--- a/source/blender/blenlib/tests/BLI_map_test.cc
+++ b/source/blender/blenlib/tests/BLI_map_test.cc
@@ -653,6 +653,18 @@ TEST(map, LookupKey)
EXPECT_EQ(map.lookup_key_ptr("a"), map.lookup_key_ptr_as("a"));
}
+TEST(map, ReferenceWrapperKey)
+{
+ Map<std::reference_wrapper<int>, int> map;
+ int a = 2;
+ int b = 5;
+ map.add(a, 10);
+ map.add(a, 20);
+ map.add(b, 20);
+ EXPECT_EQ(map.lookup(a), 10);
+ EXPECT_EQ(map.lookup(b), 20);
+}
+
/**
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
*/
More information about the Bf-blender-cvs
mailing list