From f86331a0338dc2351e914b45ccbd743b6cccbb19 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 26 Nov 2021 14:47:02 +0100 Subject: Geometry Nodes: deduplicate virtual array implementations For some underlying data (e.g. spans) we had two virtual array implementations. One for the mutable and one for the immutable case. Now that most code does not deal with the virtual array implementations directly anymore (since rBrBd4c868da9f97a), we can get away with sharing one implementation for both cases. This means that we have to do a `const_cast` in a few places, but this is an implementation detail that does not leak into "user code" (only when explicitly casting a `VArrayImpl` to a `VMutableArrayImpl`, which should happen nowhere). --- .../blender/blenkernel/intern/attribute_access.cc | 7 +- .../blenkernel/intern/geometry_component_curve.cc | 214 +++++++-------------- .../blenkernel/intern/geometry_component_mesh.cc | 43 ++--- source/blender/blenlib/BLI_virtual_array.hh | 128 +++--------- .../blender/functions/FN_generic_virtual_array.hh | 26 +-- .../functions/intern/generic_virtual_array.cc | 82 ++------ 6 files changed, 126 insertions(+), 374 deletions(-) diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 3f2c1f13337..47ddb2494d0 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -50,7 +50,7 @@ using blender::bke::AttributeIDRef; using blender::bke::OutputAttribute; using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVMutableArrayImpl_For_GMutableSpan; +using blender::fn::GVArrayImpl_For_GSpan; namespace blender::bke { @@ -1200,8 +1200,7 @@ blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeID return blender::fn::GVArray::ForSingle(*type, domain_size, default_value); } -class GVMutableAttribute_For_OutputAttribute - : public blender::fn::GVMutableArrayImpl_For_GMutableSpan { +class GVMutableAttribute_For_OutputAttribute : public blender::fn::GVArrayImpl_For_GSpan { public: GeometryComponent *component; std::string attribute_name; @@ -1210,7 +1209,7 @@ class GVMutableAttribute_For_OutputAttribute GVMutableAttribute_For_OutputAttribute(GMutableSpan data, GeometryComponent &component, const AttributeIDRef &attribute_id) - : blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component) + : blender::fn::GVArrayImpl_For_GSpan(data), component(&component) { if (attribute_id.is_named()) { this->attribute_name = attribute_id.name(); diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index 598c61fd877..a0d7bfe135a 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -713,47 +713,16 @@ static bool remove_point_attribute(GeometryComponent &component, return layer_freed; } -/** - * Virtual array for any control point data accessed with spans and an offset array. - */ -template class VArray_For_SplinePoints : public VArrayImpl { - private: - const Array> data_; - Array offsets_; - - public: - VArray_For_SplinePoints(Array> data, Array offsets) - : VArrayImpl(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) - { - } - - T get(const int64_t index) const final - { - const PointIndices indices = lookup_point_indices(offsets_, index); - return data_[indices.spline_index][indices.point_index]; - } - - void materialize(const IndexMask mask, MutableSpan r_span) const final - { - point_attribute_materialize(data_.as_span(), offsets_, mask, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final - { - point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span); - } -}; - /** * Mutable virtual array for any control point data accessed with spans and an offset array. */ -template class VMutableArray_For_SplinePoints final : public VMutableArrayImpl { +template class VArrayImpl_For_SplinePoints final : public VMutableArrayImpl { private: Array> data_; Array offsets_; public: - VMutableArray_For_SplinePoints(Array> data, Array offsets) + VArrayImpl_For_SplinePoints(Array> data, Array offsets) : VMutableArrayImpl(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } @@ -791,16 +760,17 @@ template class VMutableArray_For_SplinePoints final : public VMutabl } }; -template VArray point_data_varray(Array> spans, Array offsets) +template VArray point_data_varray(Array> spans, Array offsets) { - return VArray::template For>(std::move(spans), std::move(offsets)); + return VArray::template For>(std::move(spans), + std::move(offsets)); } template -VMutableArray point_data_varray(Array> spans, Array offsets) +VMutableArray point_data_varray_mutable(Array> spans, Array offsets) { - return VMutableArray::template For>(std::move(spans), - std::move(offsets)); + return VMutableArray::template For>(std::move(spans), + std::move(offsets)); } /** @@ -811,13 +781,13 @@ VMutableArray point_data_varray(Array> spans, Array offse * \note There is no need to check the handle type to avoid changing auto handles, since * retrieving write access to the position data will mark them for recomputation anyway. */ -class VMutableArray_For_SplinePosition final : public VMutableArrayImpl { +class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl { private: MutableSpan splines_; Array offsets_; public: - VMutableArray_For_SplinePosition(MutableSpan splines, Array offsets) + VArrayImpl_For_SplinePosition(MutableSpan splines, Array offsets) : VMutableArrayImpl(offsets.last()), splines_(splines), offsets_(std::move(offsets)) { } @@ -889,104 +859,16 @@ class VMutableArray_For_SplinePosition final : public VMutableArrayImpl } }; -class VArray_For_BezierHandle final : public VArrayImpl { - private: - Span splines_; - Array offsets_; - bool is_right_; - - public: - VArray_For_BezierHandle(Span splines, Array offsets, const bool is_right) - : VArrayImpl(offsets.last()), - splines_(std::move(splines)), - offsets_(std::move(offsets)), - is_right_(is_right) - { - } - - static float3 get_internal(const int64_t index, - Span splines, - Span offsets, - const bool is_right) - { - const PointIndices indices = lookup_point_indices(offsets, index); - const Spline &spline = *splines[indices.spline_index]; - if (spline.type() == Spline::Type::Bezier) { - const BezierSpline &bezier_spline = static_cast(spline); - return is_right ? bezier_spline.handle_positions_right()[indices.point_index] : - bezier_spline.handle_positions_left()[indices.point_index]; - } - return float3(0); - } - - float3 get(const int64_t index) const final - { - return get_internal(index, splines_, offsets_, is_right_); - } - - /** - * Utility so we can pass handle positions to the materialize functions above. - * - * \note This relies on the ability of the materialize implementations to - * handle empty spans, since only Bezier splines have handles. - */ - static Array> get_handle_spans(Span splines, const bool is_right) - { - Array> spans(splines.size()); - for (const int i : spans.index_range()) { - if (splines[i]->type() == Spline::Type::Bezier) { - BezierSpline &bezier_spline = static_cast(*splines[i]); - spans[i] = is_right ? bezier_spline.handle_positions_right() : - bezier_spline.handle_positions_left(); - } - else { - spans[i] = {}; - } - } - return spans; - } - - static void materialize_internal(const IndexMask mask, - Span splines, - Span offsets, - const bool is_right, - MutableSpan r_span) - { - Array> spans = get_handle_spans(splines, is_right); - point_attribute_materialize(spans.as_span(), offsets, mask, r_span); - } - - static void materialize_to_uninitialized_internal(const IndexMask mask, - Span splines, - Span offsets, - const bool is_right, - MutableSpan r_span) - { - Array> spans = get_handle_spans(splines, is_right); - point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span); - } - - void materialize(const IndexMask mask, MutableSpan r_span) const final - { - materialize_internal(mask, splines_, offsets_, is_right_, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final - { - materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span); - } -}; - -class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { +class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl { private: MutableSpan splines_; Array offsets_; bool is_right_; public: - VMutableArray_For_BezierHandles(MutableSpan splines, - Array offsets, - const bool is_right) + VArrayImpl_For_BezierHandles(MutableSpan splines, + Array offsets, + const bool is_right) : VMutableArrayImpl(offsets.last()), splines_(splines), offsets_(std::move(offsets)), @@ -996,7 +878,14 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { float3 get(const int64_t index) const final { - return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_); + const PointIndices indices = lookup_point_indices(offsets_, index); + const Spline &spline = *splines_[indices.spline_index]; + if (spline.type() == Spline::Type::Bezier) { + const BezierSpline &bezier_spline = static_cast(spline); + return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] : + bezier_spline.handle_positions_left()[indices.point_index]; + } + return float3(0); } void set(const int64_t index, float3 value) final @@ -1040,13 +929,36 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { void materialize(const IndexMask mask, MutableSpan r_span) const final { - VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span); + Array> spans = get_handle_spans(splines_, is_right_); + point_attribute_materialize(spans.as_span(), offsets_, mask, r_span); } void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final { - VArray_For_BezierHandle::materialize_to_uninitialized_internal( - mask, splines_, offsets_, is_right_, r_span); + Array> spans = get_handle_spans(splines_, is_right_); + point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span); + } + + /** + * Utility so we can pass handle positions to the materialize functions above. + * + * \note This relies on the ability of the materialize implementations to + * handle empty spans, since only Bezier splines have handles. + */ + static Array> get_handle_spans(Span splines, const bool is_right) + { + Array> spans(splines.size()); + for (const int i : spans.index_range()) { + if (splines[i]->type() == Spline::Type::Bezier) { + BezierSpline &bezier_spline = static_cast(*splines[i]); + spans[i] = is_right ? bezier_spline.handle_positions_right() : + bezier_spline.handle_positions_left(); + } + else { + spans[i] = {}; + } + } + return spans; } }; @@ -1102,9 +1014,12 @@ template class BuiltinPointAttributeProvider : public BuiltinAttribu } Array offsets = curve->control_point_offsets(); - Array> spans(splines.size()); + Array> spans(splines.size()); for (const int i : splines.index_range()) { - spans[i] = get_span_(*splines[i]); + Span span = get_span_(*splines[i]); + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + spans[i] = MutableSpan(const_cast(span.data()), span.size()); } return point_data_varray(spans, offsets); @@ -1143,7 +1058,7 @@ template class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_mutable_span_(*splines[i]); } - return {point_data_varray(spans, offsets), domain_, tag_modified_fn}; + return {point_data_varray_mutable(spans, offsets), domain_, tag_modified_fn}; } bool try_delete(GeometryComponent &component) const final @@ -1235,8 +1150,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider offsets = curve->control_point_offsets(); - return {VMutableArray::For(curve->splines(), - std::move(offsets)), + return {VMutableArray::For(curve->splines(), + std::move(offsets)), domain_, tag_modified_fn}; } @@ -1270,8 +1185,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { } Array offsets = curve->control_point_offsets(); - return VArray::For( - curve->splines(), std::move(offsets), is_right_); + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + return VArray::For( + const_cast(curve)->splines(), std::move(offsets), is_right_); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1288,7 +1205,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); }; Array offsets = curve->control_point_offsets(); - return {VMutableArray::For( + return {VMutableArray::For( curve->splines(), std::move(offsets), is_right_), domain_, tag_modified_fn}; @@ -1377,9 +1294,12 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { Array offsets = curve->control_point_offsets(); attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) { using T = decltype(dummy); - Array> data(splines.size()); + Array> data(splines.size()); for (const int i : splines.index_range()) { - data[i] = spans[i].typed(); + Span span = spans[i].typed(); + /* Use const-cast because the underlying virtual array implementation is shared between + * const and non const data. */ + data[i] = MutableSpan(const_cast(span.data()), span.size()); BLI_assert(data[i].data() != nullptr); } attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; @@ -1435,7 +1355,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray_mutable(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index a258a66cdf3..e7d48670f73 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -996,57 +996,36 @@ static void set_crease(MEdge &edge, float value) edge.crease = round_fl_to_uchar_clamp(value * 255.0f); } -class VMutableArray_For_VertexWeights final : public VMutableArrayImpl { +class VArrayImpl_For_VertexWeights final : public VMutableArrayImpl { private: MDeformVert *dverts_; const int dvert_index_; public: - VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index) + VArrayImpl_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index) : VMutableArrayImpl(totvert), dverts_(dverts), dvert_index_(dvert_index) { } float get(const int64_t index) const override { - return get_internal(dverts_, dvert_index_, index); - } - - void set(const int64_t index, const float value) override - { - MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_); - weight->weight = value; - } - - static float get_internal(const MDeformVert *dverts, const int dvert_index, const int64_t index) - { - if (dverts == nullptr) { + if (dverts_ == nullptr) { return 0.0f; } - const MDeformVert &dvert = dverts[index]; + const MDeformVert &dvert = dverts_[index]; for (const MDeformWeight &weight : Span(dvert.dw, dvert.totweight)) { - if (weight.def_nr == dvert_index) { + if (weight.def_nr == dvert_index_) { return weight.weight; } } return 0.0f; + ; } -}; -class VArray_For_VertexWeights final : public VArrayImpl { - private: - const MDeformVert *dverts_; - const int dvert_index_; - - public: - VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index) - : VArrayImpl(totvert), dverts_(dverts), dvert_index_(dvert_index) - { - } - - float get(const int64_t index) const override + void set(const int64_t index, const float value) override { - return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index); + MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_); + weight->weight = value; } }; @@ -1077,7 +1056,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { static const float default_value = 0.0f; return {VArray::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT}; } - return {VArray::For( + return {VArray::For( mesh->dvert, mesh->totvert, vertex_group_index), ATTR_DOMAIN_POINT}; } @@ -1109,7 +1088,7 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( &mesh->vdata, CD_MDEFORMVERT, mesh->totvert); } - return {VMutableArray::For( + return {VMutableArray::For( mesh->dvert, mesh->totvert, vertex_group_index), ATTR_DOMAIN_POINT}; } diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 33b3f82c0c2..2038abc0b77 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -223,69 +223,21 @@ template class VMutableArrayImpl : public VArrayImpl { }; /** - * A virtual array implementation for a span. Methods in this class are final so that it can be - * devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used). + * A virtual array implementation that references that wraps a span. This implementation is used by + * mutable and immutable spans to avoid code duplication. */ -template class VArrayImpl_For_Span : public VArrayImpl { - protected: - const T *data_ = nullptr; - - public: - VArrayImpl_For_Span(const Span data) : VArrayImpl(data.size()), data_(data.data()) - { - } - - protected: - VArrayImpl_For_Span(const int64_t size) : VArrayImpl(size) - { - } - - T get(const int64_t index) const final - { - return data_[index]; - } - - bool is_span() const final - { - return true; - } - - Span get_internal_span() const final - { - return Span(data_, this->size_); - } -}; - -/** - * A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the - * #may_have_ownership method. - */ -template class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span { - public: - using VArrayImpl_For_Span::VArrayImpl_For_Span; - - private: - bool may_have_ownership() const override - { - return false; - } -}; - -/** - * Like #VArrayImpl_For_Span but for mutable data. - */ -template class VMutableArrayImpl_For_MutableSpan : public VMutableArrayImpl { +template class VArrayImpl_For_Span : public VMutableArrayImpl { protected: T *data_ = nullptr; public: - VMutableArrayImpl_For_MutableSpan(const MutableSpan data) + VArrayImpl_For_Span(const MutableSpan data) : VMutableArrayImpl(data.size()), data_(data.data()) { } protected: - VMutableArrayImpl_For_MutableSpan(const int64_t size) : VMutableArrayImpl(size) + VArrayImpl_For_Span(const int64_t size) : VMutableArrayImpl(size) { } @@ -311,12 +263,12 @@ template class VMutableArrayImpl_For_MutableSpan : public VMutableAr }; /** - * Like #VArrayImpl_For_Span_final but for mutable data. + * A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the + * #may_have_ownership method. */ -template -class VMutableArrayImpl_For_MutableSpan_final final : public VMutableArrayImpl_For_MutableSpan { +template class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span { public: - using VMutableArrayImpl_For_MutableSpan::VMutableArrayImpl_For_MutableSpan; + using VArrayImpl_For_Span::VArrayImpl_For_Span; private: bool may_have_ownership() const override @@ -340,7 +292,7 @@ class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span { VArrayImpl_For_ArrayContainer(Container container) : VArrayImpl_For_Span((int64_t)container.size()), container_(std::move(container)) { - this->data_ = container_.data(); + this->data_ = const_cast(container_.data()); } }; @@ -419,57 +371,19 @@ template class VArrayImpl_For_Func final : public } }; -/** - * \note: This is `final` so that #may_have_ownership can be implemented reliably. - */ -template -class VArrayImpl_For_DerivedSpan final : public VArrayImpl { - private: - const StructT *data_; - - public: - VArrayImpl_For_DerivedSpan(const Span data) - : VArrayImpl(data.size()), data_(data.data()) - { - } - - private: - ElemT get(const int64_t index) const override - { - return GetFunc(data_[index]); - } - - void materialize(IndexMask mask, MutableSpan r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); }); - } - - void materialize_to_uninitialized(IndexMask mask, MutableSpan r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); }); - } - - bool may_have_ownership() const override - { - return false; - } -}; - /** * \note: This is `final` so that #may_have_ownership can be implemented reliably. */ template -class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl { + void (*SetFunc)(StructT &, ElemT) = nullptr> +class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl { private: StructT *data_; public: - VMutableArrayImpl_For_DerivedSpan(const MutableSpan data) + VArrayImpl_For_DerivedSpan(const MutableSpan data) : VMutableArrayImpl(data.size()), data_(data.data()) { } @@ -482,6 +396,7 @@ class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl void set(const int64_t index, ElemT value) override { + BLI_assert(SetFunc != nullptr); SetFunc(data_[index], std::move(value)); } @@ -840,7 +755,10 @@ template class VArray : public VArrayCommon { */ static VArray ForSpan(Span values) { - return VArray::For>(values); + /* Cast const away, because the virtual array implementation for const and non const spans is + * shared. */ + MutableSpan span{const_cast(values.data()), values.size()}; + return VArray::For>(span); } /** @@ -859,7 +777,10 @@ template class VArray : public VArrayCommon { template static VArray ForDerivedSpan(Span values) { - return VArray::For>(values); + /* Cast const away, because the virtual array implementation for const and non const derived + * spans is shared. */ + MutableSpan span{const_cast(values.data()), values.size()}; + return VArray::For>(span); } /** @@ -919,7 +840,7 @@ template class VMutableArray : public VArrayCommon { */ static VMutableArray ForSpan(MutableSpan values) { - return VMutableArray::For>(values); + return VMutableArray::For>(values); } /** @@ -929,8 +850,7 @@ template class VMutableArray : public VArrayCommon { template static VMutableArray ForDerivedSpan(MutableSpan values) { - return VMutableArray::For>( - values); + return VMutableArray::For>(values); } /** Convert to a #VArray by copying. */ diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh index b822f3a7c33..aed7c206fe5 100644 --- a/source/blender/functions/FN_generic_virtual_array.hh +++ b/source/blender/functions/FN_generic_virtual_array.hh @@ -555,37 +555,19 @@ template class VMutableArrayImpl_For_GVMutableArray : public VMutabl /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl_For_GSpan and #GVMutableArrayImpl_For_GMutableSpan. +/** \name #GVArrayImpl_For_GSpan. * \{ */ -class GVArrayImpl_For_GSpan : public GVArrayImpl { - protected: - const void *data_ = nullptr; - const int64_t element_size_; - - public: - GVArrayImpl_For_GSpan(const GSpan span); - - protected: - GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size); - - void get(const int64_t index, void *r_value) const override; - void get_to_uninitialized(const int64_t index, void *r_value) const override; - - bool is_span() const override; - GSpan get_internal_span() const override; -}; - -class GVMutableArrayImpl_For_GMutableSpan : public GVMutableArrayImpl { +class GVArrayImpl_For_GSpan : public GVMutableArrayImpl { protected: void *data_ = nullptr; const int64_t element_size_; public: - GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span); + GVArrayImpl_For_GSpan(const GMutableSpan span); protected: - GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, const int64_t size); + GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size); public: void get(const int64_t index, void *r_value) const override; diff --git a/source/blender/functions/intern/generic_virtual_array.cc b/source/blender/functions/intern/generic_virtual_array.cc index b8f44c15c2f..415445eebd6 100644 --- a/source/blender/functions/intern/generic_virtual_array.cc +++ b/source/blender/functions/intern/generic_virtual_array.cc @@ -139,107 +139,56 @@ bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const /** \name #GVArrayImpl_For_GSpan * \{ */ -GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span) - : GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size()) -{ -} - -GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size) - : GVArrayImpl(type, size), element_size_(type.size()) -{ -} - -void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const -{ - type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value); -} - -void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const -{ - type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value); -} - -bool GVArrayImpl_For_GSpan::is_span() const -{ - return true; -} - -GSpan GVArrayImpl_For_GSpan::get_internal_span() const -{ - return GSpan(*type_, data_, size_); -} - -/** See #VArrayImpl_For_Span_final. */ -class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan { - public: - using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan; - - private: - bool may_have_ownership() const override - { - return false; - } -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVMutableArrayImpl_For_GMutableSpan - * \{ */ - -GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span) +GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GMutableSpan span) : GVMutableArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size()) { } -GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, - const int64_t size) +GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size) : GVMutableArrayImpl(type, size), element_size_(type.size()) { } -void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const +void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const { type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value); } -void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index, - void *r_value) const +void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const { type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value); } -void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value) +void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value) { type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index)); } -void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value) +void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value) { type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index)); } -void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value) +void GVArrayImpl_For_GSpan::set_by_relocate(const int64_t index, void *value) { type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index)); } -bool GVMutableArrayImpl_For_GMutableSpan::is_span() const +bool GVArrayImpl_For_GSpan::is_span() const { return true; } -GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const +GSpan GVArrayImpl_For_GSpan::get_internal_span() const { return GSpan(*type_, data_, size_); } -class GVMutableArrayImpl_For_GMutableSpan_final final - : public GVMutableArrayImpl_For_GMutableSpan { +class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan { public: - using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan; + using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan; private: bool may_have_ownership() const override @@ -682,7 +631,10 @@ GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size) GVArray GVArray::ForSpan(GSpan span) { - return GVArray::For(span); + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + GMutableSpan mutable_span{span.type(), const_cast(span.data()), span.size()}; + return GVArray::For(mutable_span); } class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan { @@ -691,7 +643,7 @@ class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan { public: GVArrayImpl_For_GArray(GArray<> array) - : GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array)) + : GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array)) { } }; @@ -743,7 +695,7 @@ GVMutableArray::GVMutableArray(std::shared_ptr impl) GVMutableArray GVMutableArray::ForSpan(GMutableSpan span) { - return GVMutableArray::For(span); + return GVMutableArray::For(span); } GVMutableArray::operator GVArray() const & -- cgit v1.2.3