[Bf-blender-cvs] [87114836328] master: BLI: generalize converting CPPType to static type
Jacques Lucke
noreply at git.blender.org
Sat Mar 19 10:57:59 CET 2022
Commit: 8711483632823524019a6cc95575c5a4ba5aa831
Author: Jacques Lucke
Date: Sat Mar 19 10:57:40 2022 +0100
Branches: master
https://developer.blender.org/rB8711483632823524019a6cc95575c5a4ba5aa831
BLI: generalize converting CPPType to static type
Previously, the conversion was done manually for a fixed set of types.
Now, there is a more general utility that can be used in other contexts
(outside of geometry nodes attribute processing) as well.
===================================================================
M source/blender/blenkernel/BKE_attribute_access.hh
M source/blender/blenkernel/BKE_attribute_math.hh
M source/blender/blenkernel/BKE_customdata.h
M source/blender/blenkernel/intern/attribute_access.cc
M source/blender/blenkernel/intern/customdata.cc
M source/blender/blenlib/BLI_cpp_type.hh
M source/blender/blenlib/intern/cpp_type.cc
M source/blender/blenlib/tests/BLI_cpp_type_test.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index 36f29c7fbb7..8d449a124ec 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -164,8 +164,6 @@ using AttributeForeachCallback = blender::FunctionRef<bool(
namespace blender::bke {
-const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
-CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types);
/**
* Domains with a higher "information density" have a higher priority,
diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
index 9e97979fde9..3075c0689e9 100644
--- a/source/blender/blenkernel/BKE_attribute_math.hh
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -8,71 +8,34 @@
#include "BLI_math_vector.h"
#include "BLI_math_vector.hh"
-#include "DNA_customdata_types.h"
+#include "BKE_customdata.h"
namespace blender::attribute_math {
/**
- * Utility function that simplifies calling a templated function based on a custom data type.
+ * Utility function that simplifies calling a templated function based on a run-time data type.
*/
template<typename Func>
-inline void convert_to_static_type(const CustomDataType data_type, const Func &func)
+inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
{
- switch (data_type) {
- case CD_PROP_FLOAT:
- func(float());
- break;
- case CD_PROP_FLOAT2:
- func(float2());
- break;
- case CD_PROP_FLOAT3:
- func(float3());
- break;
- case CD_PROP_INT32:
- func(int());
- break;
- case CD_PROP_BOOL:
- func(bool());
- break;
- case CD_PROP_INT8:
- func(int8_t());
- break;
- case CD_PROP_COLOR:
- func(ColorGeometry4f());
- break;
- default:
- BLI_assert_unreachable();
- break;
- }
+ cpp_type.to_static_type_tag<float, float2, float3, int, bool, int8_t, ColorGeometry4f>(
+ [&](auto type_tag) {
+ using T = typename decltype(type_tag)::type;
+ if constexpr (std::is_same_v<T, void>) {
+ /* It's expected that the given cpp type is one of the supported once. */
+ BLI_assert_unreachable();
+ }
+ else {
+ func(T());
+ }
+ });
}
template<typename Func>
-inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
+inline void convert_to_static_type(const CustomDataType data_type, const Func &func)
{
- if (cpp_type.is<float>()) {
- func(float());
- }
- else if (cpp_type.is<float2>()) {
- func(float2());
- }
- else if (cpp_type.is<float3>()) {
- func(float3());
- }
- else if (cpp_type.is<int>()) {
- func(int());
- }
- else if (cpp_type.is<bool>()) {
- func(bool());
- }
- else if (cpp_type.is<int8_t>()) {
- func(int8_t());
- }
- else if (cpp_type.is<ColorGeometry4f>()) {
- func(ColorGeometry4f());
- }
- else {
- BLI_assert_unreachable();
- }
+ const CPPType &cpp_type = *bke::custom_data_type_to_cpp_type(data_type);
+ convert_to_static_type(cpp_type, func);
}
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 940dc3c4f6c..911f4aab394 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -751,3 +751,12 @@ void CustomData_debug_info_from_layers(const struct CustomData *data,
#ifdef __cplusplus
}
#endif
+
+#ifdef __cplusplus
+# include "BLI_cpp_type.hh"
+
+namespace blender::bke {
+const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
+CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
+} // namespace blender::bke
+#endif
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 50e35c3c7c2..8fbab8dde25 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -54,55 +54,6 @@ std::ostream &operator<<(std::ostream &stream, const AttributeIDRef &attribute_i
return stream;
}
-const blender::CPPType *custom_data_type_to_cpp_type(const CustomDataType type)
-{
- switch (type) {
- case CD_PROP_FLOAT:
- return &CPPType::get<float>();
- case CD_PROP_FLOAT2:
- return &CPPType::get<float2>();
- case CD_PROP_FLOAT3:
- return &CPPType::get<float3>();
- case CD_PROP_INT32:
- return &CPPType::get<int>();
- case CD_PROP_COLOR:
- return &CPPType::get<ColorGeometry4f>();
- case CD_PROP_BOOL:
- return &CPPType::get<bool>();
- case CD_PROP_INT8:
- return &CPPType::get<int8_t>();
- default:
- return nullptr;
- }
- return nullptr;
-}
-
-CustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
-{
- if (type.is<float>()) {
- return CD_PROP_FLOAT;
- }
- if (type.is<float2>()) {
- return CD_PROP_FLOAT2;
- }
- if (type.is<float3>()) {
- return CD_PROP_FLOAT3;
- }
- if (type.is<int>()) {
- return CD_PROP_INT32;
- }
- if (type.is<ColorGeometry4f>()) {
- return CD_PROP_COLOR;
- }
- if (type.is<bool>()) {
- return CD_PROP_BOOL;
- }
- if (type.is<int8_t>()) {
- return CD_PROP_INT8;
- }
- return static_cast<CustomDataType>(-1);
-}
-
static int attribute_data_type_complexity(const CustomDataType data_type)
{
switch (data_type) {
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index b348e18a6a8..251d73dc315 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -18,9 +18,11 @@
#include "DNA_meshdata_types.h"
#include "BLI_bitmap.h"
+#include "BLI_color.hh"
#include "BLI_endian_switch.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
+#include "BLI_math_vector.hh"
#include "BLI_mempool.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@@ -5234,3 +5236,56 @@ void CustomData_debug_info_from_layers(const CustomData *data, const char *inden
}
#endif /* NDEBUG */
+
+namespace blender::bke {
+
+const blender::CPPType *custom_data_type_to_cpp_type(const CustomDataType type)
+{
+ switch (type) {
+ case CD_PROP_FLOAT:
+ return &CPPType::get<float>();
+ case CD_PROP_FLOAT2:
+ return &CPPType::get<float2>();
+ case CD_PROP_FLOAT3:
+ return &CPPType::get<float3>();
+ case CD_PROP_INT32:
+ return &CPPType::get<int>();
+ case CD_PROP_COLOR:
+ return &CPPType::get<ColorGeometry4f>();
+ case CD_PROP_BOOL:
+ return &CPPType::get<bool>();
+ case CD_PROP_INT8:
+ return &CPPType::get<int8_t>();
+ default:
+ return nullptr;
+ }
+ return nullptr;
+}
+
+CustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
+{
+ if (type.is<float>()) {
+ return CD_PROP_FLOAT;
+ }
+ if (type.is<float2>()) {
+ return CD_PROP_FLOAT2;
+ }
+ if (type.is<float3>()) {
+ return CD_PROP_FLOAT3;
+ }
+ if (type.is<int>()) {
+ return CD_PROP_INT32;
+ }
+ if (type.is<ColorGeometry4f>()) {
+ return CD_PROP_COLOR;
+ }
+ if (type.is<bool>()) {
+ return CD_PROP_BOOL;
+ }
+ if (type.is<int8_t>()) {
+ return CD_PROP_INT8;
+ }
+ return static_cast<CustomDataType>(-1);
+}
+
+} // namespace blender::bke
diff --git a/source/blender/blenlib/BLI_cpp_type.hh b/source/blender/blenlib/BLI_cpp_type.hh
index ae6a87b4b68..881408f460b 100644
--- a/source/blender/blenlib/BLI_cpp_type.hh
+++ b/source/blender/blenlib/BLI_cpp_type.hh
@@ -22,6 +22,7 @@
* - If the code is not performance sensitive, it usually makes sense to use #CPPType instead.
* - Sometimes a combination can make sense. Optimized code can be be generated at compile-time for
* some types, while there is a fallback code path using #CPPType for all other types.
+ * #CPPType::to_static_type allows dispatching between both versions based on the type.
*
* Under some circumstances, #CPPType serves a similar role as #std::type_info. However, #CPPType
* has much more utility because it contains methods for actually working with instances of the
@@ -71,6 +72,7 @@
#include "BLI_hash.hh"
#include "BLI_index_mask.hh"
+#include "BLI_map.hh"
#include "BLI_math_base.h"
#include "BLI_string_ref.hh"
#include "BLI_utility_mixins.hh"
@@ -643,6 +645,77 @@ class CPPType : NonCopyable, NonMovable {
{
return this == &CPPType::get<std::decay_t<T>>();
}
+
+ /**
+ * Convert a #CPPType that is only known at run-time, to a static type that is known at
+ * compile-time. This allows the compiler to optimize a function for specific types, while all
+ * other types can still use a generic fallback function.
+ *
+ * \param Types The types that code should be generated for.
+ * \param fn The function object to call. This is expected to have a templated `operator()` and a
+ * non-templated `operator()`. The templated version will be called if the current #CPPType
+ * matches any of the given types. Otherwise, the non-templated function is called.
+ */
+ template<typename... Types, typename Fn> void to_static_type(const Fn &fn) const
+ {
+ using Callback = void (*)(const Fn &fn);
+
+ /* Build a lookup table to avoid having to compare the current #CPPType with every type in
+ * #Types one after another. */
+ static const Map<const CPPType *, Callback> callback_map = []() {
+ Map<const CPPType *, Callback> callback_map;
+ /* This adds an entry in the map for every type in #Types. */
+ (callback_map.add_new(&CPPType::get<Types>(),
+ [](const Fn &fn) {
+ /* Call the templated `operator()` of the given function object. */
+ fn.template operator()<Types>();
+ }),
+ ...);
+ return callback_map;
+ }();
+
+ const Callback callback = callback_map.lookup_default(this, nullptr);
+ if (callback != nullptr) {
+ cal
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list