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-26 17:33:21 +0300
committerJacques Lucke <jacques@blender.org>2021-11-26 17:33:35 +0300
commit602ecbdf9aef58a4e3c8d7ea5db22a913bf60525 (patch)
tree91a9c05b13f44034e75070b825b35565e7c39b58 /source/blender/blenlib
parenteb7827e7970cca8e3fb0e0bf39e8742e69f0b2b6 (diff)
Geometry Nodes: optimize Set Position node
This implements four optimizations in the Set Position node: * Check whether the position input is the current position and ignore it if it is. This results in a speedup when only the Offset input is used. * Use multi-threading when copying to computed values to the position attribute. All geometry types benefit from this. * Use devirtualization for the offset and position input. This optimizes the common case that they are either single values or computed in the fly in a span. * Write to `Mesh->mvert` directly instead of creating a temporary span. This makes setting mesh vertex positions even more efficient. In my simple benchmark I'm using a White Noise node to offset the position of 1,000,000 vertices. The speed is `20 ms -> 4.5 ms` in the multi-threaded case and `32 ms -> 22 ms` in the single-threaded case.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_virtual_array.hh63
1 files changed, 63 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh
index 2038abc0b77..85e9cb25b3f 100644
--- a/source/blender/blenlib/BLI_virtual_array.hh
+++ b/source/blender/blenlib/BLI_virtual_array.hh
@@ -183,6 +183,15 @@ template<typename T> class VArrayImpl {
* own anything can overwrite this with false. */
return true;
}
+
+ /**
+ * Return true when the other virtual array should be considered to be the same, e.g. because it
+ * shares the same underlying memory.
+ */
+ virtual bool is_same(const VArrayImpl<T> &UNUSED(other)) const
+ {
+ return false;
+ }
};
/* Similar to #VArrayImpl, but adds methods that allow modifying the referenced elements. */
@@ -260,6 +269,18 @@ template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> {
{
return Span<T>(data_, this->size_);
}
+
+ bool is_same(const VArrayImpl<T> &other) const final
+ {
+ if (other.size() != this->size_) {
+ return false;
+ }
+ if (!other.is_span()) {
+ return false;
+ }
+ const Span<T> other_span = other.get_internal_span();
+ return data_ == other_span.data();
+ }
};
/**
@@ -388,6 +409,12 @@ class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> {
{
}
+ template<typename OtherStructT,
+ typename OtherElemT,
+ OtherElemT (*OtherGetFunc)(const OtherStructT &),
+ void (*OtherSetFunc)(OtherStructT &, OtherElemT)>
+ friend class VArrayImpl_For_DerivedSpan;
+
private:
ElemT get(const int64_t index) const override
{
@@ -416,6 +443,23 @@ class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> {
{
return false;
}
+
+ bool is_same(const VArrayImpl<ElemT> &other) const override
+ {
+ if (other.size() != this->size_) {
+ return false;
+ }
+ if (const VArrayImpl_For_DerivedSpan<StructT, ElemT, GetFunc> *other_typed =
+ dynamic_cast<const VArrayImpl_For_DerivedSpan<StructT, ElemT, GetFunc> *>(&other)) {
+ return other_typed->data_ == data_;
+ }
+ if (const VArrayImpl_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc> *other_typed =
+ dynamic_cast<const VArrayImpl_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc> *>(
+ &other)) {
+ return other_typed->data_ == data_;
+ }
+ return false;
+ }
};
namespace detail {
@@ -670,6 +714,25 @@ template<typename T> class VArrayCommon {
return impl_->get_internal_single();
}
+ /**
+ * Return true when the other virtual references the same underlying memory.
+ */
+ bool is_same(const VArrayCommon<T> &other) const
+ {
+ if (!*this || !other) {
+ return false;
+ }
+ /* Check in both directions in case one does not know how to compare to the other
+ * implementation. */
+ if (impl_->is_same(*other.impl_)) {
+ return true;
+ }
+ if (other.impl_->is_same(*impl_)) {
+ return true;
+ }
+ return false;
+ }
+
/** Copy the entire virtual array into a span. */
void materialize(MutableSpan<T> r_span) const
{