diff options
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 @@ -714,46 +714,15 @@ static bool remove_point_attribute(GeometryComponent &component, } /** - * Virtual array for any control point data accessed with spans and an offset array. - */ -template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> { - private: - const Array<Span<T>> data_; - Array<int> offsets_; - - public: - VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets) - : VArrayImpl<T>(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<T> r_span) const final - { - point_attribute_materialize(data_.as_span(), offsets_, mask, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> 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<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> { +template<typename T> class VArrayImpl_For_SplinePoints final : public VMutableArrayImpl<T> { private: Array<MutableSpan<T>> data_; Array<int> offsets_; public: - VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets) + VArrayImpl_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets) : VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } @@ -791,16 +760,17 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl } }; -template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets) +template<typename T> VArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets) { - return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets)); + return VArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans), + std::move(offsets)); } template<typename T> -VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets) +VMutableArray<T> point_data_varray_mutable(Array<MutableSpan<T>> spans, Array<int> offsets) { - return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans), - std::move(offsets)); + return VMutableArray<T>::template For<VArrayImpl_For_SplinePoints<T>>(std::move(spans), + std::move(offsets)); } /** @@ -811,13 +781,13 @@ VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> 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<float3> { +class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; public: - VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets) + VArrayImpl_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets) : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)) { } @@ -889,104 +859,16 @@ class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> } }; -class VArray_For_BezierHandle final : public VArrayImpl<float3> { - private: - Span<SplinePtr> splines_; - Array<int> offsets_; - bool is_right_; - - public: - VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right) - : VArrayImpl<float3>(offsets.last()), - splines_(std::move(splines)), - offsets_(std::move(offsets)), - is_right_(is_right) - { - } - - static float3 get_internal(const int64_t index, - Span<SplinePtr> splines, - Span<int> 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<const BezierSpline &>(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<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right) - { - Array<Span<float3>> spans(splines.size()); - for (const int i : spans.index_range()) { - if (splines[i]->type() == Spline::Type::Bezier) { - BezierSpline &bezier_spline = static_cast<BezierSpline &>(*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<SplinePtr> splines, - Span<int> offsets, - const bool is_right, - MutableSpan<float3> r_span) - { - Array<Span<float3>> 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<SplinePtr> splines, - Span<int> offsets, - const bool is_right, - MutableSpan<float3> r_span) - { - Array<Span<float3>> 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<float3> r_span) const final - { - materialize_internal(mask, splines_, offsets_, is_right_, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final - { - materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span); - } -}; - -class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> { +class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; bool is_right_; public: - VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines, - Array<int> offsets, - const bool is_right) + VArrayImpl_For_BezierHandles(MutableSpan<SplinePtr> splines, + Array<int> offsets, + const bool is_right) : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)), @@ -996,7 +878,14 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> { 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<const BezierSpline &>(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<float3> { void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { - VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span); + Array<Span<float3>> 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<float3> r_span) const final { - VArray_For_BezierHandle::materialize_to_uninitialized_internal( - mask, splines_, offsets_, is_right_, r_span); + Array<Span<float3>> 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<Span<float3>> get_handle_spans(Span<SplinePtr> splines, const bool is_right) + { + Array<Span<float3>> spans(splines.size()); + for (const int i : spans.index_range()) { + if (splines[i]->type() == Spline::Type::Bezier) { + BezierSpline &bezier_spline = static_cast<BezierSpline &>(*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<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu } Array<int> offsets = curve->control_point_offsets(); - Array<Span<T>> spans(splines.size()); + Array<MutableSpan<T>> spans(splines.size()); for (const int i : splines.index_range()) { - spans[i] = get_span_(*splines[i]); + Span<T> 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<T>(const_cast<T *>(span.data()), span.size()); } return point_data_varray(spans, offsets); @@ -1143,7 +1058,7 @@ template<typename T> 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<flo }; Array<int> offsets = curve->control_point_offsets(); - return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(), - std::move(offsets)), + return {VMutableArray<float3>::For<VArrayImpl_For_SplinePosition>(curve->splines(), + std::move(offsets)), domain_, tag_modified_fn}; } @@ -1270,8 +1185,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { } Array<int> offsets = curve->control_point_offsets(); - return VArray<float3>::For<VArray_For_BezierHandle>( - 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<float3>::For<VArrayImpl_For_BezierHandles>( + const_cast<CurveEval *>(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<int> offsets = curve->control_point_offsets(); - return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>( + return {VMutableArray<float3>::For<VArrayImpl_For_BezierHandles>( curve->splines(), std::move(offsets), is_right_), domain_, tag_modified_fn}; @@ -1377,9 +1294,12 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { Array<int> offsets = curve->control_point_offsets(); attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) { using T = decltype(dummy); - Array<Span<T>> data(splines.size()); + Array<MutableSpan<T>> data(splines.size()); for (const int i : splines.index_range()) { - data[i] = spans[i].typed<T>(); + Span<T> span = spans[i].typed<T>(); + /* Use const-cast because the underlying virtual array implementation is shared between + * const and non const data. */ + data[i] = MutableSpan<T>(const_cast<T *>(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<T>(); 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<float> { +class VArrayImpl_For_VertexWeights final : public VMutableArrayImpl<float> { 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<float>(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<float> { - private: - const MDeformVert *dverts_; - const int dvert_index_; - - public: - VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index) - : VArrayImpl<float>(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<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT}; } - return {VArray<float>::For<VArray_For_VertexWeights>( + return {VArray<float>::For<VArrayImpl_For_VertexWeights>( 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<float>::For<VMutableArray_For_VertexWeights>( + return {VMutableArray<float>::For<VArrayImpl_For_VertexWeights>( 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<typename T> class VMutableArrayImpl : public VArrayImpl<T> { }; /** - * 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<typename T> class VArrayImpl_For_Span : public VArrayImpl<T> { - protected: - const T *data_ = nullptr; - - public: - VArrayImpl_For_Span(const Span<T> data) : VArrayImpl<T>(data.size()), data_(data.data()) - { - } - - protected: - VArrayImpl_For_Span(const int64_t size) : VArrayImpl<T>(size) - { - } - - T get(const int64_t index) const final - { - return data_[index]; - } - - bool is_span() const final - { - return true; - } - - Span<T> get_internal_span() const final - { - return Span<T>(data_, this->size_); - } -}; - -/** - * A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the - * #may_have_ownership method. - */ -template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> { - public: - using VArrayImpl_For_Span<T>::VArrayImpl_For_Span; - - private: - bool may_have_ownership() const override - { - return false; - } -}; - -/** - * Like #VArrayImpl_For_Span but for mutable data. - */ -template<typename T> class VMutableArrayImpl_For_MutableSpan : public VMutableArrayImpl<T> { +template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> { protected: T *data_ = nullptr; public: - VMutableArrayImpl_For_MutableSpan(const MutableSpan<T> data) + VArrayImpl_For_Span(const MutableSpan<T> data) : VMutableArrayImpl<T>(data.size()), data_(data.data()) { } protected: - VMutableArrayImpl_For_MutableSpan(const int64_t size) : VMutableArrayImpl<T>(size) + VArrayImpl_For_Span(const int64_t size) : VMutableArrayImpl<T>(size) { } @@ -311,12 +263,12 @@ template<typename T> 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<typename T> -class VMutableArrayImpl_For_MutableSpan_final final : public VMutableArrayImpl_For_MutableSpan<T> { +template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> { public: - using VMutableArrayImpl_For_MutableSpan<T>::VMutableArrayImpl_For_MutableSpan; + using VArrayImpl_For_Span<T>::VArrayImpl_For_Span; private: bool may_have_ownership() const override @@ -340,7 +292,7 @@ class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span<T> { VArrayImpl_For_ArrayContainer(Container container) : VArrayImpl_For_Span<T>((int64_t)container.size()), container_(std::move(container)) { - this->data_ = container_.data(); + this->data_ = const_cast<T *>(container_.data()); } }; @@ -422,54 +374,16 @@ template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public /** * \note: This is `final` so that #may_have_ownership can be implemented reliably. */ -template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> -class VArrayImpl_For_DerivedSpan final : public VArrayImpl<ElemT> { - private: - const StructT *data_; - - public: - VArrayImpl_For_DerivedSpan(const Span<StructT> data) - : VArrayImpl<ElemT>(data.size()), data_(data.data()) - { - } - - private: - ElemT get(const int64_t index) const override - { - return GetFunc(data_[index]); - } - - void materialize(IndexMask mask, MutableSpan<ElemT> 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<ElemT> 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<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &), - void (*SetFunc)(StructT &, ElemT)> -class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> { + void (*SetFunc)(StructT &, ElemT) = nullptr> +class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> { private: StructT *data_; public: - VMutableArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data) + VArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data) : VMutableArrayImpl<ElemT>(data.size()), data_(data.data()) { } @@ -482,6 +396,7 @@ class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> void set(const int64_t index, ElemT value) override { + BLI_assert(SetFunc != nullptr); SetFunc(data_[index], std::move(value)); } @@ -840,7 +755,10 @@ template<typename T> class VArray : public VArrayCommon<T> { */ static VArray ForSpan(Span<T> values) { - return VArray::For<VArrayImpl_For_Span_final<T>>(values); + /* Cast const away, because the virtual array implementation for const and non const spans is + * shared. */ + MutableSpan<T> span{const_cast<T *>(values.data()), values.size()}; + return VArray::For<VArrayImpl_For_Span_final<T>>(span); } /** @@ -859,7 +777,10 @@ template<typename T> class VArray : public VArrayCommon<T> { template<typename StructT, T (*GetFunc)(const StructT &)> static VArray ForDerivedSpan(Span<StructT> values) { - return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(values); + /* Cast const away, because the virtual array implementation for const and non const derived + * spans is shared. */ + MutableSpan<StructT> span{const_cast<StructT *>(values.data()), values.size()}; + return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(span); } /** @@ -919,7 +840,7 @@ template<typename T> class VMutableArray : public VArrayCommon<T> { */ static VMutableArray ForSpan(MutableSpan<T> values) { - return VMutableArray::For<VMutableArrayImpl_For_MutableSpan_final<T>>(values); + return VMutableArray::For<VArrayImpl_For_Span_final<T>>(values); } /** @@ -929,8 +850,7 @@ template<typename T> class VMutableArray : public VArrayCommon<T> { template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)> static VMutableArray ForDerivedSpan(MutableSpan<StructT> values) { - return VMutableArray::For<VMutableArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>( - values); + return VMutableArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>(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<typename T> 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<GVArrayImpl_For_GSpan_final>(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<void *>(span.data()), span.size()}; + return GVArray::For<GVArrayImpl_For_GSpan_final>(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<GVMutableArrayImpl> impl) GVMutableArray GVMutableArray::ForSpan(GMutableSpan span) { - return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span); + return GVMutableArray::For<GVArrayImpl_For_GSpan_final>(span); } GVMutableArray::operator GVArray() const & |