This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/functions/intern/generic_virtual_array.cc
Jacques Lucke 3608891282 Functions: extend virtual array functionality
This adds support for mutable virtual arrays and provides many utilities
for creating virtual arrays for various kinds of data. This commit is
preparation for D10994.
2021-04-17 15:13:20 +02:00

298 lines
7.8 KiB
C++

/*
* 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_generic_virtual_array.hh"
namespace blender::fn {
/* --------------------------------------------------------------------
* GVArray.
*/
void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const
{
for (const int64_t i : mask) {
void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
this->get_to_uninitialized(i, elem_dst);
}
}
void GVArray::get_impl(const int64_t index, void *r_value) const
{
type_->destruct(r_value);
this->get_to_uninitialized_impl(index, r_value);
}
bool GVArray::is_span_impl() const
{
return false;
}
GSpan GVArray::get_internal_span_impl() const
{
BLI_assert(false);
return GSpan(*type_);
}
bool GVArray::is_single_impl() const
{
return false;
}
void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const
{
BLI_assert(false);
}
const void *GVArray::try_get_internal_varray_impl() const
{
return nullptr;
}
/* --------------------------------------------------------------------
* GVMutableArray.
*/
void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value)
{
BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer);
type_->copy_to_uninitialized(value, buffer);
this->set_by_move_impl(index, buffer);
type_->destruct(buffer);
}
void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value)
{
this->set_by_move_impl(index, value);
type_->destruct(value);
}
void *GVMutableArray::try_get_internal_mutable_varray_impl()
{
return nullptr;
}
void GVMutableArray::fill(const void *value)
{
if (this->is_span()) {
const GMutableSpan span = this->get_internal_span();
type_->fill_initialized(value, span.data(), size_);
}
else {
for (int64_t i : IndexRange(size_)) {
this->set_by_copy(i, value);
}
}
}
/* --------------------------------------------------------------------
* GVArray_For_GSpan.
*/
void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const
{
type_->copy_to_initialized(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const
{
type_->copy_to_uninitialized(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
bool GVArray_For_GSpan::is_span_impl() const
{
return true;
}
GSpan GVArray_For_GSpan::get_internal_span_impl() const
{
return GSpan(*type_, data_, size_);
}
/* --------------------------------------------------------------------
* GVMutableArray_For_GMutableSpan.
*/
void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const
{
type_->copy_to_initialized(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index,
void *r_value) const
{
type_->copy_to_uninitialized(POINTER_OFFSET(data_, element_size_ * index), r_value);
}
void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value)
{
type_->copy_to_initialized(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value)
{
type_->move_to_initialized(value, POINTER_OFFSET(data_, element_size_ * index));
}
void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value)
{
type_->relocate_to_initialized(value, POINTER_OFFSET(data_, element_size_ * index));
}
bool GVMutableArray_For_GMutableSpan::is_span_impl() const
{
return true;
}
GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const
{
return GSpan(*type_, data_, size_);
}
/* --------------------------------------------------------------------
* GVArray_For_SingleValueRef.
*/
void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const
{
type_->copy_to_initialized(value_, r_value);
}
void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index),
void *r_value) const
{
type_->copy_to_uninitialized(value_, r_value);
}
bool GVArray_For_SingleValueRef::is_span_impl() const
{
return size_ == 1;
}
GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const
{
return GSpan{*type_, value_, 1};
}
bool GVArray_For_SingleValueRef::is_single_impl() const
{
return true;
}
void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const
{
type_->copy_to_initialized(value_, r_value);
}
/* --------------------------------------------------------------------
* GVArray_For_SingleValue.
*/
GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type,
const int64_t size,
const void *value)
: GVArray_For_SingleValueRef(type, size)
{
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
type.copy_to_uninitialized(value, (void *)value_);
}
GVArray_For_SingleValue::~GVArray_For_SingleValue()
{
type_->destruct((void *)value_);
MEM_freeN((void *)value_);
}
/* --------------------------------------------------------------------
* GVArray_GSpan.
*/
GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray)
{
size_ = varray_.size();
if (varray_.is_span()) {
data_ = varray_.get_internal_span().data();
}
else {
owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__);
varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
data_ = owned_data_;
}
}
GVArray_GSpan::~GVArray_GSpan()
{
if (owned_data_ != nullptr) {
type_->destruct_n(owned_data_, size_);
MEM_freeN(owned_data_);
}
}
/* --------------------------------------------------------------------
* GVMutableArray_GSpan.
*/
GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span)
: GMutableSpan(varray.type()), varray_(varray)
{
size_ = varray_.size();
if (varray_.is_span()) {
data_ = varray_.get_internal_span().data();
}
else {
owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__);
if (copy_values_to_span) {
varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
}
else {
type_->construct_default_n(owned_data_, size_);
}
data_ = owned_data_;
}
}
GVMutableArray_GSpan::~GVMutableArray_GSpan()
{
if (show_not_saved_warning_) {
if (!save_has_been_called_) {
std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n";
}
}
if (owned_data_ != nullptr) {
type_->destruct_n(owned_data_, size_);
MEM_freeN(owned_data_);
}
}
void GVMutableArray_GSpan::save()
{
save_has_been_called_ = true;
if (data_ != owned_data_) {
return;
}
const int64_t element_size = type_->size();
for (int64_t i : IndexRange(size_)) {
varray_.set_by_copy(i, POINTER_OFFSET(owned_data_, element_size * i));
}
}
void GVMutableArray_GSpan::disable_not_applied_warning()
{
show_not_saved_warning_ = false;
}
} // namespace blender::fn