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>2020-06-08 18:37:43 +0300
committerJacques Lucke <jacques@blender.org>2020-06-08 18:37:43 +0300
commit0a907657d4d525d320e0c8518f583b7210736214 (patch)
tree10ca57cfaa0af568686ed309af163e32442a87e5 /source/blender/functions
parentb5846ebce7863a59f6bbd00cf676486a7b4e0b76 (diff)
Functions: Run-time type system and index mask
This adds a new `CPPType` that encapsulates information about how to handle instances of a specific data type. This is necessary for the function evaluation system, which will be used to evaluate most of the particle node trees. Furthermore, this adds an `IndexMask` class which offers a surprisingly useful abstraction over an array containing unsigned integers. It makes two assumptions about the underlying integer array: * The integers are in ascending order. * There are no duplicates. `IndexMask` will be used to "select" certain particles that will be processed in a data-oriented way. Sometimes, operations don't have to be applied to all particles, but only some, those that are in the indexed by the `IndexMask`. The two limitations imposed by an `IndexMask` allow for better performance. Reviewers: brecht Differential Revision: https://developer.blender.org/D7957
Diffstat (limited to 'source/blender/functions')
-rw-r--r--source/blender/functions/CMakeLists.txt40
-rw-r--r--source/blender/functions/FN_cpp_type.hh726
-rw-r--r--source/blender/functions/FN_cpp_types.hh48
-rw-r--r--source/blender/functions/intern/cpp_types.cc41
4 files changed, 855 insertions, 0 deletions
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
new file mode 100644
index 00000000000..9ce1d3ac2fe
--- /dev/null
+++ b/source/blender/functions/CMakeLists.txt
@@ -0,0 +1,40 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../blenlib
+ ../makesdna
+ ../../../intern/guardedalloc
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/cpp_types.cc
+
+ FN_cpp_type.hh
+ FN_cpp_types.hh
+)
+
+set(LIB
+ bf_blenlib
+)
+
+blender_add_lib(bf_functions "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
new file mode 100644
index 00000000000..10e95c0341e
--- /dev/null
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -0,0 +1,726 @@
+/*
+ * 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.
+ */
+
+#ifndef __FN_CPP_TYPE_HH__
+#define __FN_CPP_TYPE_HH__
+
+/** \file
+ * \ingroup functions
+ *
+ * The CPPType class is the core of the runtime-type-system used by the functions system. An
+ * instance of this class can represent any C++ type, that is default-constructable, destructable,
+ * movable and copyable. Therefore it also works for all C types. This restrictions might need to
+ * be removed in the future, but for now every required type has these properties.
+ *
+ * Every type has a size and an alignment. Every function dealing with C++ types in a generic way,
+ * has to make sure that alignment rules are followed. The methods provided by a CPPType instance
+ * will check for correct alignment as well.
+ *
+ * Every type has a name that is for debugging purposes only. It should not be used as identifier.
+ *
+ * To check if two instances of CPPType represent the same type, only their pointers have to be
+ * compared. Any C++ type has at most one corresponding CPPType instance.
+ *
+ * A CPPType instance comes with many methods that allow dealing with types in a generic way. Most
+ * methods come in three variants. Using the construct-default methods as example:
+ * - construct_default(void *ptr):
+ * Constructs a single instance of that type at the given pointer.
+ * - construct_default_n(void *ptr, uint n):
+ * Constructs n instances of that type in an array that starts at the given pointer.
+ * - construct_default_indices(void *ptr, IndexMask index_mask):
+ * Constructs multiple instances of that type in an array that starts at the given pointer.
+ * Only the indices referenced by `index_mask` will by constructed.
+ *
+ * In some cases default-construction does nothing (e.g. for trivial types like int). The
+ * `default_value` method provides some default value anyway that can be copied instead. What the
+ * default value is, depends on the type. Usually it is something like 0 or an empty string.
+ *
+ *
+ * Implementation Considerations
+ * -----------------------------
+ *
+ * Concepts like inheritance are currently not captured by this system. This is not because it is
+ * not possible, but because it was not necessary to add this complexity yet.
+ *
+ * One could also implement CPPType itself using virtual inheritance. However, I found the approach
+ * used now with explicit function pointers to work better. Here are some reasons:
+ * - If CPPType would be inherited once for every used C++ type, we would get a lot of classes
+ * that would only be instanced once each.
+ * - Methods like `construct_default` that operate on a single instance have to be fast. Even this
+ * one necessary indirection using function pointers adds a lot of overhead. If all methods were
+ * virtual, there would be a second level of indirection that increases the overhead even more.
+ * - If it becomes necessary, we could pass the function pointers to C functions more easily than
+ * pointers to virtual member functions.
+ */
+
+#include "BLI_index_mask.hh"
+#include "BLI_math_base.h"
+#include "BLI_string_ref.hh"
+
+namespace FN {
+
+using BLI::IndexMask;
+using BLI::StringRef;
+using BLI::StringRefNull;
+
+class CPPType {
+ public:
+ using ConstructDefaultF = void (*)(void *ptr);
+ using ConstructDefaultNF = void (*)(void *ptr, uint n);
+ using ConstructDefaultIndicesF = void (*)(void *ptr, IndexMask index_mask);
+
+ using DestructF = void (*)(void *ptr);
+ using DestructNF = void (*)(void *ptr, uint n);
+ using DestructIndicesF = void (*)(void *ptr, IndexMask index_mask);
+
+ using CopyToInitializedF = void (*)(const void *src, void *dst);
+ using CopyToInitializedNF = void (*)(const void *src, void *dst, uint n);
+ using CopyToInitializedIndicesF = void (*)(const void *src, void *dst, IndexMask index_mask);
+
+ using CopyToUninitializedF = void (*)(const void *src, void *dst);
+ using CopyToUninitializedNF = void (*)(const void *src, void *dst, uint n);
+ using CopyToUninitializedIndicesF = void (*)(const void *src, void *dst, IndexMask index_mask);
+
+ using RelocateToInitializedF = void (*)(void *src, void *dst);
+ using RelocateToInitializedNF = void (*)(void *src, void *dst, uint n);
+ using RelocateToInitializedIndicesF = void (*)(void *src, void *dst, IndexMask index_mask);
+
+ using RelocateToUninitializedF = void (*)(void *src, void *dst);
+ using RelocateToUninitializedNF = void (*)(void *src, void *dst, uint n);
+ using RelocateToUninitializedIndicesF = void (*)(void *src, void *dst, IndexMask index_mask);
+
+ using FillInitializedF = void (*)(const void *value, void *dst, uint n);
+ using FillInitializedIndicesF = void (*)(const void *value, void *dst, IndexMask index_mask);
+
+ using FillUninitializedF = void (*)(const void *value, void *dst, uint n);
+ using FillUninitializedIndicesF = void (*)(const void *value, void *dst, IndexMask index_mask);
+
+ CPPType(std::string name,
+ uint size,
+ uint alignment,
+ bool is_trivially_destructible,
+ ConstructDefaultF construct_default,
+ ConstructDefaultNF construct_default_n,
+ ConstructDefaultIndicesF construct_default_indices,
+ DestructF destruct,
+ DestructNF destruct_n,
+ DestructIndicesF destruct_indices,
+ CopyToInitializedF copy_to_initialized,
+ CopyToInitializedNF copy_to_initialized_n,
+ CopyToInitializedIndicesF copy_to_initialized_indices,
+ CopyToUninitializedF copy_to_uninitialized,
+ CopyToUninitializedNF copy_to_uninitialized_n,
+ CopyToUninitializedIndicesF copy_to_uninitialized_indices,
+ RelocateToInitializedF relocate_to_initialized,
+ RelocateToInitializedNF relocate_to_initialized_n,
+ RelocateToInitializedIndicesF relocate_to_initialized_indices,
+ RelocateToUninitializedF relocate_to_uninitialized,
+ RelocateToUninitializedNF relocate_to_uninitialized_n,
+ RelocateToUninitializedIndicesF relocate_to_uninitialized_indices,
+ FillInitializedF fill_initialized,
+ FillInitializedIndicesF fill_initialized_indices,
+ FillUninitializedF fill_uninitialized,
+ FillUninitializedIndicesF fill_uninitialized_indices,
+ const void *default_value)
+ : m_size(size),
+ m_alignment(alignment),
+ m_is_trivially_destructible(is_trivially_destructible),
+ m_construct_default(construct_default),
+ m_construct_default_n(construct_default_n),
+ m_construct_default_indices(construct_default_indices),
+ m_destruct(destruct),
+ m_destruct_n(destruct_n),
+ m_destruct_indices(destruct_indices),
+ m_copy_to_initialized(copy_to_initialized),
+ m_copy_to_initialized_n(copy_to_initialized_n),
+ m_copy_to_initialized_indices(copy_to_initialized_indices),
+ m_copy_to_uninitialized(copy_to_uninitialized),
+ m_copy_to_uninitialized_n(copy_to_uninitialized_n),
+ m_copy_to_uninitialized_indices(copy_to_uninitialized_indices),
+ m_relocate_to_initialized(relocate_to_initialized),
+ m_relocate_to_initialized_n(relocate_to_initialized_n),
+ m_relocate_to_initialized_indices(relocate_to_initialized_indices),
+ m_relocate_to_uninitialized(relocate_to_uninitialized),
+ m_relocate_to_uninitialized_n(relocate_to_uninitialized_n),
+ m_relocate_to_uninitialized_indices(relocate_to_uninitialized_indices),
+ m_fill_initialized(fill_initialized),
+ m_fill_initialized_indices(fill_initialized_indices),
+ m_fill_uninitialized(fill_uninitialized),
+ m_fill_uninitialized_indices(fill_uninitialized_indices),
+ m_default_value(default_value),
+ m_name(name)
+ {
+ BLI_assert(is_power_of_2_i(m_alignment));
+ m_alignment_mask = (uintptr_t)m_alignment - (uintptr_t)1;
+ }
+
+ /**
+ * Returns the name of the type for debugging purposes. This name should not be used as
+ * identifier.
+ */
+ StringRefNull name() const
+ {
+ return m_name;
+ }
+
+ /**
+ * Required memory in bytes for an instance of this type.
+ *
+ * C++ equivalent:
+ * sizeof(T);
+ */
+ uint size() const
+ {
+ return m_size;
+ }
+
+ /**
+ * Required memory alignment for an instance of this type.
+ *
+ * C++ equivalent:
+ * alignof(T);
+ */
+ uint alignment() const
+ {
+ return m_alignment;
+ }
+
+ /**
+ * When true, the destructor does not have to be called on this type. This can sometimes be used
+ * for optimization purposes.
+ *
+ * C++ equivalent:
+ * std::is_trivially_destructible<T>::value;
+ */
+ bool is_trivially_destructible() const
+ {
+ return m_is_trivially_destructible;
+ }
+
+ /**
+ * Returns true, when the given pointer fullfills the alignment requirement of this type.
+ */
+ bool pointer_has_valid_alignment(const void *ptr) const
+ {
+ return ((uintptr_t)ptr & m_alignment_mask) == 0;
+ }
+
+ bool pointer_can_point_to_instance(const void *ptr) const
+ {
+ return ptr != nullptr && pointer_has_valid_alignment(ptr);
+ }
+
+ /**
+ * Call the default constructor at the given memory location.
+ * The memory should be uninitialized before this method is called.
+ * For some trivial types (like int), this method does nothing.
+ *
+ * C++ equivalent:
+ * new (ptr) T;
+ */
+ void construct_default(void *ptr) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_construct_default(ptr);
+ }
+
+ void construct_default_n(void *ptr, uint n) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_construct_default_n(ptr, n);
+ }
+
+ void construct_default_indices(void *ptr, IndexMask index_mask) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_construct_default_indices(ptr, index_mask);
+ }
+
+ /**
+ * Call the destructor on the given instance of this type. The pointer must not be nullptr.
+ *
+ * For some trivial types, this does nothing.
+ *
+ * C++ equivalent:
+ * ptr->~T();
+ */
+ void destruct(void *ptr) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_destruct(ptr);
+ }
+
+ void destruct_n(void *ptr, uint n) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_destruct_n(ptr, n);
+ }
+
+ void destruct_indices(void *ptr, IndexMask index_mask) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(ptr));
+
+ m_destruct_indices(ptr, index_mask);
+ }
+
+ /**
+ * Copy an instance of this type from src to dst.
+ *
+ * C++ equivalent:
+ * dst = src;
+ */
+ void copy_to_initialized(const void *src, void *dst) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_initialized(src, dst);
+ }
+
+ void copy_to_initialized_n(const void *src, void *dst, uint n) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_initialized_n(src, dst, n);
+ }
+
+ void copy_to_initialized_indices(const void *src, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_initialized_indices(src, dst, index_mask);
+ }
+
+ /**
+ * Copy an instance of this type from src to dst.
+ *
+ * The memory pointed to by dst should be uninitialized.
+ *
+ * C++ equivalent:
+ * new (dst) T(src);
+ */
+ void copy_to_uninitialized(const void *src, void *dst) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_uninitialized(src, dst);
+ }
+
+ void copy_to_uninitialized_n(const void *src, void *dst, uint n) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_uninitialized_n(src, dst, n);
+ }
+
+ void copy_to_uninitialized_indices(const void *src, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_copy_to_uninitialized_indices(src, dst, index_mask);
+ }
+
+ /**
+ * Relocates an instance of this type from src to dst. src will point to uninitialized memory
+ * afterwards.
+ *
+ * C++ equivalent:
+ * dst = std::move(src);
+ * src->~T();
+ */
+ void relocate_to_initialized(void *src, void *dst) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_initialized(src, dst);
+ }
+
+ void relocate_to_initialized_n(void *src, void *dst, uint n) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_initialized_n(src, dst, n);
+ }
+
+ void relocate_to_initialized_indices(void *src, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_initialized_indices(src, dst, index_mask);
+ }
+
+ /**
+ * Relocates an instance of this type from src to dst. src will point to uninitialized memory
+ * afterwards.
+ *
+ * C++ equivalent:
+ * new (dst) T(std::move(src))
+ * src->~T();
+ */
+ void relocate_to_uninitialized(void *src, void *dst) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_uninitialized(src, dst);
+ }
+
+ void relocate_to_uninitialized_n(void *src, void *dst, uint n) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_uninitialized_n(src, dst, n);
+ }
+
+ void relocate_to_uninitialized_indices(void *src, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(src != dst);
+ BLI_assert(this->pointer_can_point_to_instance(src));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_relocate_to_uninitialized_indices(src, dst, index_mask);
+ }
+
+ /**
+ * Copy the given value to the first n elements in an array starting at dst.
+ *
+ * Other instances of the same type should live in the array before this method is called.
+ */
+ void fill_initialized(const void *value, void *dst, uint n) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(value));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_fill_initialized(value, dst, n);
+ }
+
+ void fill_initialized_indices(const void *value, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(value));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_fill_initialized_indices(value, dst, index_mask);
+ }
+
+ /**
+ * Copy the given value to the first n elements in an array starting at dst.
+ *
+ * The array should be uninitialized before this method is called.
+ */
+ void fill_uninitialized(const void *value, void *dst, uint n) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(value));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_fill_uninitialized(value, dst, n);
+ }
+
+ void fill_uninitialized_indices(const void *value, void *dst, IndexMask index_mask) const
+ {
+ BLI_assert(this->pointer_can_point_to_instance(value));
+ BLI_assert(this->pointer_can_point_to_instance(dst));
+
+ m_fill_uninitialized_indices(value, dst, index_mask);
+ }
+
+ /**
+ * Get a pointer to a constant value of this type. The specific value depends on the type.
+ * It is usually a zero-initialized or default constructed value.
+ */
+ const void *default_value() const
+ {
+ return m_default_value;
+ }
+
+ /**
+ * Two types only compare equal when their pointer is equal. No two instances of CPPType for the
+ * same C++ type should be created.
+ */
+ friend bool operator==(const CPPType &a, const CPPType &b)
+ {
+ return &a == &b;
+ }
+
+ friend bool operator!=(const CPPType &a, const CPPType &b)
+ {
+ return !(&a == &b);
+ }
+
+ template<typename T> static const CPPType &get();
+
+ private:
+ uint m_size;
+ uint m_alignment;
+ uintptr_t m_alignment_mask;
+ bool m_is_trivially_destructible;
+
+ ConstructDefaultF m_construct_default;
+ ConstructDefaultNF m_construct_default_n;
+ ConstructDefaultIndicesF m_construct_default_indices;
+
+ DestructF m_destruct;
+ DestructNF m_destruct_n;
+ DestructIndicesF m_destruct_indices;
+
+ CopyToInitializedF m_copy_to_initialized;
+ CopyToInitializedNF m_copy_to_initialized_n;
+ CopyToInitializedIndicesF m_copy_to_initialized_indices;
+
+ CopyToUninitializedF m_copy_to_uninitialized;
+ CopyToUninitializedNF m_copy_to_uninitialized_n;
+ CopyToUninitializedIndicesF m_copy_to_uninitialized_indices;
+
+ RelocateToInitializedF m_relocate_to_initialized;
+ RelocateToInitializedNF m_relocate_to_initialized_n;
+ RelocateToInitializedIndicesF m_relocate_to_initialized_indices;
+
+ RelocateToUninitializedF m_relocate_to_uninitialized;
+ RelocateToUninitializedNF m_relocate_to_uninitialized_n;
+ RelocateToUninitializedIndicesF m_relocate_to_uninitialized_indices;
+
+ FillInitializedF m_fill_initialized;
+ FillInitializedIndicesF m_fill_initialized_indices;
+
+ FillUninitializedF m_fill_uninitialized;
+ FillUninitializedIndicesF m_fill_uninitialized_indices;
+
+ const void *m_default_value;
+ std::string m_name;
+};
+
+/* --------------------------------------------------------------------
+ * Utility for creating CPPType instances for C++ types.
+ */
+
+namespace CPPTypeUtil {
+
+template<typename T> void construct_default_cb(void *ptr)
+{
+ BLI::construct_default((T *)ptr);
+}
+template<typename T> void construct_default_n_cb(void *ptr, uint n)
+{
+ for (uint i = 0; i < n; i++) {
+ BLI::construct_default((T *)ptr + i);
+ }
+}
+template<typename T> void construct_default_indices_cb(void *ptr, IndexMask index_mask)
+{
+ index_mask.foreach_index([&](uint i) { BLI::construct_default((T *)ptr + i); });
+}
+
+template<typename T> void destruct_cb(void *ptr)
+{
+ BLI::destruct((T *)ptr);
+}
+template<typename T> void destruct_n_cb(void *ptr, uint n)
+{
+ BLI::destruct_n((T *)ptr, n);
+}
+template<typename T> void destruct_indices_cb(void *ptr, IndexMask index_mask)
+{
+ index_mask.foreach_index([&](uint i) { BLI::destruct((T *)ptr + i); });
+}
+
+template<typename T> void copy_to_initialized_cb(const void *src, void *dst)
+{
+ *(T *)dst = *(T *)src;
+}
+template<typename T> void copy_to_initialized_n_cb(const void *src, void *dst, uint n)
+{
+ const T *src_ = (const T *)src;
+ T *dst_ = (T *)dst;
+
+ for (uint i = 0; i < n; i++) {
+ dst_[i] = src_[i];
+ }
+}
+template<typename T>
+void copy_to_initialized_indices_cb(const void *src, void *dst, IndexMask index_mask)
+{
+ const T *src_ = (const T *)src;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) { dst_[i] = src_[i]; });
+}
+
+template<typename T> void copy_to_uninitialized_cb(const void *src, void *dst)
+{
+ BLI::uninitialized_copy_n((T *)src, 1, (T *)dst);
+}
+template<typename T> void copy_to_uninitialized_n_cb(const void *src, void *dst, uint n)
+{
+ BLI::uninitialized_copy_n((T *)src, n, (T *)dst);
+}
+template<typename T>
+void copy_to_uninitialized_indices_cb(const void *src, void *dst, IndexMask index_mask)
+{
+ const T *src_ = (const T *)src;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) { new (dst_ + i) T(src_[i]); });
+}
+
+template<typename T> void relocate_to_initialized_cb(void *src, void *dst)
+{
+ BLI::relocate((T *)src, (T *)dst);
+}
+template<typename T> void relocate_to_initialized_n_cb(void *src, void *dst, uint n)
+{
+ BLI::relocate_n((T *)src, n, (T *)dst);
+}
+template<typename T>
+void relocate_to_initialized_indices_cb(void *src, void *dst, IndexMask index_mask)
+{
+ T *src_ = (T *)src;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) {
+ dst_[i] = std::move(src_[i]);
+ src_[i].~T();
+ });
+}
+
+template<typename T> void relocate_to_uninitialized_cb(void *src, void *dst)
+{
+ BLI::uninitialized_relocate((T *)src, (T *)dst);
+}
+template<typename T> void relocate_to_uninitialized_n_cb(void *src, void *dst, uint n)
+{
+ BLI::uninitialized_relocate_n((T *)src, n, (T *)dst);
+}
+template<typename T>
+void relocate_to_uninitialized_indices_cb(void *src, void *dst, IndexMask index_mask)
+{
+ T *src_ = (T *)src;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) {
+ new (dst_ + i) T(std::move(src_[i]));
+ src_[i].~T();
+ });
+}
+
+template<typename T> void fill_initialized_cb(const void *value, void *dst, uint n)
+{
+ const T &value_ = *(const T *)value;
+ T *dst_ = (T *)dst;
+
+ for (uint i = 0; i < n; i++) {
+ dst_[i] = value_;
+ }
+}
+template<typename T>
+void fill_initialized_indices_cb(const void *value, void *dst, IndexMask index_mask)
+{
+ const T &value_ = *(const T *)value;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) { dst_[i] = value_; });
+}
+
+template<typename T> void fill_uninitialized_cb(const void *value, void *dst, uint n)
+{
+ const T &value_ = *(const T *)value;
+ T *dst_ = (T *)dst;
+
+ for (uint i = 0; i < n; i++) {
+ new (dst_ + i) T(value_);
+ }
+}
+template<typename T>
+void fill_uninitialized_indices_cb(const void *value, void *dst, IndexMask index_mask)
+{
+ const T &value_ = *(const T *)value;
+ T *dst_ = (T *)dst;
+
+ index_mask.foreach_index([&](uint i) { new (dst_ + i) T(value_); });
+}
+
+} // namespace CPPTypeUtil
+
+template<typename T>
+static std::unique_ptr<const CPPType> create_cpp_type(StringRef name, const T &default_value)
+{
+ using namespace CPPTypeUtil;
+ const CPPType *type = new CPPType(name,
+ sizeof(T),
+ alignof(T),
+ std::is_trivially_destructible<T>::value,
+ construct_default_cb<T>,
+ construct_default_n_cb<T>,
+ construct_default_indices_cb<T>,
+ destruct_cb<T>,
+ destruct_n_cb<T>,
+ destruct_indices_cb<T>,
+ copy_to_initialized_cb<T>,
+ copy_to_initialized_n_cb<T>,
+ copy_to_initialized_indices_cb<T>,
+ copy_to_uninitialized_cb<T>,
+ copy_to_uninitialized_n_cb<T>,
+ copy_to_uninitialized_indices_cb<T>,
+ relocate_to_initialized_cb<T>,
+ relocate_to_initialized_n_cb<T>,
+ relocate_to_initialized_indices_cb<T>,
+ relocate_to_uninitialized_cb<T>,
+ relocate_to_uninitialized_n_cb<T>,
+ relocate_to_uninitialized_indices_cb<T>,
+ fill_initialized_cb<T>,
+ fill_initialized_indices_cb<T>,
+ fill_uninitialized_cb<T>,
+ fill_uninitialized_indices_cb<T>,
+ (const void *)&default_value);
+ return std::unique_ptr<const CPPType>(type);
+}
+
+} // namespace FN
+
+#define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME) \
+ static TYPE_NAME default_value_##IDENTIFIER; \
+ static std::unique_ptr<const FN::CPPType> CPPTYPE_##IDENTIFIER##_owner = \
+ FN::create_cpp_type<TYPE_NAME>(STRINGIFY(IDENTIFIER), default_value_##IDENTIFIER); \
+ const FN::CPPType &CPPType_##IDENTIFIER = *CPPTYPE_##IDENTIFIER##_owner; \
+ template<> const FN::CPPType &FN::CPPType::get<TYPE_NAME>() \
+ { \
+ return CPPType_##IDENTIFIER; \
+ }
+
+#endif /* __FN_CPP_TYPE_HH__ */
diff --git a/source/blender/functions/FN_cpp_types.hh b/source/blender/functions/FN_cpp_types.hh
new file mode 100644
index 00000000000..eceb43beb9d
--- /dev/null
+++ b/source/blender/functions/FN_cpp_types.hh
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef __FN_CPP_TYPES_HH__
+#define __FN_CPP_TYPES_HH__
+
+/** \file
+ * \ingroup functions
+ *
+ * This header provides convenient access to CPPType instances for some core types like integer
+ * types.
+ */
+
+#include "FN_cpp_type.hh"
+
+namespace FN {
+
+extern const CPPType &CPPType_bool;
+
+extern const CPPType &CPPType_float;
+extern const CPPType &CPPType_float3;
+extern const CPPType &CPPType_float4x4;
+
+extern const CPPType &CPPType_int32;
+extern const CPPType &CPPType_uint32;
+extern const CPPType &CPPType_uint8;
+
+extern const CPPType &CPPType_Color4f;
+extern const CPPType &CPPType_Color4b;
+
+extern const CPPType &CPPType_string;
+
+} // namespace FN
+
+#endif /* __FN_CPP_TYPES_HH__ */
diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc
new file mode 100644
index 00000000000..3435c9c6eca
--- /dev/null
+++ b/source/blender/functions/intern/cpp_types.cc
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "FN_cpp_types.hh"
+
+#include "BLI_color.hh"
+#include "BLI_float2.hh"
+#include "BLI_float3.hh"
+#include "BLI_float4x4.hh"
+
+namespace FN {
+
+MAKE_CPP_TYPE(bool, bool)
+
+MAKE_CPP_TYPE(float, float)
+MAKE_CPP_TYPE(float3, BLI::float3)
+MAKE_CPP_TYPE(float4x4, BLI::float4x4)
+
+MAKE_CPP_TYPE(int32, int32_t)
+MAKE_CPP_TYPE(uint32, uint32_t)
+MAKE_CPP_TYPE(uint8, uint8_t)
+
+MAKE_CPP_TYPE(Color4f, BLI::Color4f)
+MAKE_CPP_TYPE(Color4b, BLI::Color4b)
+
+MAKE_CPP_TYPE(string, std::string)
+
+} // namespace FN