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/FN_generic_virtual_array.hh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

972 lines
26 KiB
C++
Raw Normal View History

Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
/*
* 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.
*/
#pragma once
/** \file
* \ingroup fn
*
* A generic virtual array is the same as a virtual array from blenlib, except for the fact that
* the data type is only known at runtime.
*/
#include <optional>
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
#include "BLI_virtual_array.hh"
#include "FN_generic_array.hh"
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
#include "FN_generic_span.hh"
namespace blender::fn {
template<typename T> class GVArray_Typed;
template<typename T> class GVMutableArray_Typed;
class GVArray;
class GVMutableArray;
using GVArrayPtr = std::unique_ptr<GVArray>;
using GVMutableArrayPtr = std::unique_ptr<GVMutableArray>;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
/* A generically typed version of `VArray<T>`. */
class GVArray {
protected:
const CPPType *type_;
int64_t size_;
public:
GVArray(const CPPType &type, const int64_t size) : type_(&type), size_(size)
{
BLI_assert(size_ >= 0);
}
virtual ~GVArray() = default;
const CPPType &type() const
{
return *type_;
}
int64_t size() const
{
return size_;
}
bool is_empty() const
{
return size_ == 0;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
/* Copies the value at the given index into the provided storage. The `r_value` pointer is
* expected to point to initialized memory. */
void get(const int64_t index, void *r_value) const
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
this->get_impl(index, r_value);
}
/* Same as `get`, but `r_value` is expected to point to uninitialized memory. */
void get_to_uninitialized(const int64_t index, void *r_value) const
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
this->get_to_uninitialized_impl(index, r_value);
}
/* Returns true when the virtual array is stored as a span internally. */
bool is_span() const
{
if (size_ == 0) {
return true;
}
return this->is_span_impl();
}
/* Returns the internally used span of the virtual array. This invokes undefined behavior is the
* virtual array is not stored as a span internally. */
GSpan get_internal_span() const
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
BLI_assert(this->is_span());
if (size_ == 0) {
return GSpan(*type_);
}
return this->get_internal_span_impl();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
/* Returns true when the virtual array returns the same value for every index. */
bool is_single() const
{
if (size_ == 1) {
return true;
}
return this->is_single_impl();
}
/* Copies the value that is used for every element into `r_value`, which is expected to point to
* initialized memory. This invokes undefined behavior if the virtual array would not return the
* same value for every index. */
void get_internal_single(void *r_value) const
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
BLI_assert(this->is_single());
if (size_ == 1) {
this->get(0, r_value);
2021-04-30 13:11:01 +02:00
return;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
this->get_internal_single_impl(r_value);
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
/* Same as `get_internal_single`, but `r_value` points to initialized memory. */
void get_internal_single_to_uninitialized(void *r_value) const
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
type_->default_construct(r_value);
this->get_internal_single(r_value);
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
void materialize(void *dst) const;
void materialize(const IndexMask mask, void *dst) const;
void materialize_to_uninitialized(void *dst) const;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
void materialize_to_uninitialized(const IndexMask mask, void *dst) const;
template<typename T> const VArray<T> *try_get_internal_varray() const
{
BLI_assert(type_->is<T>());
return (const VArray<T> *)this->try_get_internal_varray_impl();
}
/* Create a typed virtual array for this generic virtual array. */
template<typename T> GVArray_Typed<T> typed() const
{
return GVArray_Typed<T>(*this);
}
GVArrayPtr shallow_copy() const;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
protected:
virtual void get_impl(const int64_t index, void *r_value) const;
virtual void get_to_uninitialized_impl(const int64_t index, void *r_value) const = 0;
virtual bool is_span_impl() const;
virtual GSpan get_internal_span_impl() const;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
virtual bool is_single_impl() const;
virtual void get_internal_single_impl(void *UNUSED(r_value)) const;
virtual void materialize_impl(const IndexMask mask, void *dst) const;
virtual void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const;
virtual const void *try_get_internal_varray_impl() const;
};
/* Similar to GVArray, but supports changing the elements in the virtual array. */
class GVMutableArray : public GVArray {
public:
GVMutableArray(const CPPType &type, const int64_t size) : GVArray(type, size)
{
}
void set_by_copy(const int64_t index, const void *value)
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
this->set_by_copy_impl(index, value);
}
void set_by_move(const int64_t index, void *value)
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
this->set_by_move_impl(index, value);
}
void set_by_relocate(const int64_t index, void *value)
{
BLI_assert(index >= 0);
BLI_assert(index < size_);
this->set_by_relocate_impl(index, value);
}
GMutableSpan get_internal_span()
{
BLI_assert(this->is_span());
GSpan span = static_cast<const GVArray *>(this)->get_internal_span();
return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size());
}
template<typename T> VMutableArray<T> *try_get_internal_mutable_varray()
{
BLI_assert(type_->is<T>());
return (VMutableArray<T> *)this->try_get_internal_mutable_varray_impl();
}
/* Create a typed virtual array for this generic virtual array. */
template<typename T> GVMutableArray_Typed<T> typed()
{
return GVMutableArray_Typed<T>(*this);
}
void fill(const void *value);
/* Copy the values from the source buffer to all elements in the virtual array. */
void set_all(const void *src)
{
this->set_all_impl(src);
}
protected:
virtual void set_by_copy_impl(const int64_t index, const void *value);
virtual void set_by_relocate_impl(const int64_t index, void *value);
virtual void set_by_move_impl(const int64_t index, void *value) = 0;
virtual void set_all_impl(const void *src);
virtual void *try_get_internal_mutable_varray_impl();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
};
class GVArray_For_GSpan : public GVArray {
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
protected:
const void *data_ = nullptr;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
const int64_t element_size_;
public:
GVArray_For_GSpan(const GSpan span)
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
: GVArray(span.type(), span.size()), data_(span.data()), element_size_(span.type().size())
{
}
protected:
GVArray_For_GSpan(const CPPType &type, const int64_t size)
: GVArray(type, size), element_size_(type.size())
{
}
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
void get_impl(const int64_t index, void *r_value) const override;
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
bool is_span_impl() const override;
GSpan get_internal_span_impl() const override;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
};
class GVArray_For_Empty : public GVArray {
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
public:
GVArray_For_Empty(const CPPType &type) : GVArray(type, 0)
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
}
protected:
void get_to_uninitialized_impl(const int64_t UNUSED(index), void *UNUSED(r_value)) const override
{
BLI_assert(false);
}
};
class GVMutableArray_For_GMutableSpan : public GVMutableArray {
protected:
void *data_ = nullptr;
const int64_t element_size_;
public:
GVMutableArray_For_GMutableSpan(const GMutableSpan span)
: GVMutableArray(span.type(), span.size()),
data_(span.data()),
element_size_(span.type().size())
{
}
protected:
GVMutableArray_For_GMutableSpan(const CPPType &type, const int64_t size)
: GVMutableArray(type, size), element_size_(type.size())
{
}
void get_impl(const int64_t index, void *r_value) const override;
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
void set_by_copy_impl(const int64_t index, const void *value) override;
void set_by_move_impl(const int64_t index, void *value) override;
void set_by_relocate_impl(const int64_t index, void *value) override;
bool is_span_impl() const override;
GSpan get_internal_span_impl() const override;
};
/* Generic virtual array where each element has the same value. The value is not owned. */
class GVArray_For_SingleValueRef : public GVArray {
protected:
const void *value_ = nullptr;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
public:
GVArray_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
: GVArray(type, size), value_(value)
{
}
protected:
GVArray_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArray(type, size)
{
}
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
void get_impl(const int64_t index, void *r_value) const override;
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
bool is_span_impl() const override;
GSpan get_internal_span_impl() const override;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
bool is_single_impl() const override;
void get_internal_single_impl(void *r_value) const override;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
};
/* Same as GVArray_For_SingleValueRef, but the value is owned. */
class GVArray_For_SingleValue : public GVArray_For_SingleValueRef {
public:
GVArray_For_SingleValue(const CPPType &type, const int64_t size, const void *value);
~GVArray_For_SingleValue();
};
/* Used to convert a typed virtual array into a generic one. */
template<typename T> class GVArray_For_VArray : public GVArray {
protected:
const VArray<T> *varray_ = nullptr;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
public:
GVArray_For_VArray(const VArray<T> &varray)
: GVArray(CPPType::get<T>(), varray.size()), varray_(&varray)
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
}
protected:
GVArray_For_VArray(const int64_t size) : GVArray(CPPType::get<T>(), size)
{
}
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
void get_impl(const int64_t index, void *r_value) const override
{
*(T *)r_value = varray_->get(index);
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
{
new (r_value) T(varray_->get(index));
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
bool is_span_impl() const override
{
return varray_->is_span();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
GSpan get_internal_span_impl() const override
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
return GSpan(varray_->get_internal_span());
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
bool is_single_impl() const override
{
return varray_->is_single();
}
void get_internal_single_impl(void *r_value) const override
{
*(T *)r_value = varray_->get_internal_single();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
void materialize_impl(const IndexMask mask, void *dst) const override
{
varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
{
varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
const void *try_get_internal_varray_impl() const override
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
return varray_;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
};
class GVArray_For_GArray : public GVArray_For_GSpan {
protected:
GArray<> array_;
public:
GVArray_For_GArray(GArray<> array) : GVArray_For_GSpan(array.as_span()), array_(std::move(array))
{
}
};
/* Used to convert any generic virtual array into a typed one. */
template<typename T> class VArray_For_GVArray : public VArray<T> {
protected:
const GVArray *varray_ = nullptr;
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
public:
VArray_For_GVArray(const GVArray &varray) : VArray<T>(varray.size()), varray_(&varray)
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
BLI_assert(varray_->type().template is<T>());
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
protected:
VArray_For_GVArray(const int64_t size) : VArray<T>(size)
{
}
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
T get_impl(const int64_t index) const override
{
T value;
varray_->get(index, &value);
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
return value;
}
bool is_span_impl() const override
{
return varray_->is_span();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
Span<T> get_internal_span_impl() const override
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
return varray_->get_internal_span().template typed<T>();
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
bool is_single_impl() const override
{
return varray_->is_single();
}
T get_internal_single_impl() const override
{
T value;
varray_->get_internal_single(&value);
return value;
}
};
/* Used to convert an generic mutable virtual array into a typed one. */
template<typename T> class VMutableArray_For_GVMutableArray : public VMutableArray<T> {
protected:
GVMutableArray *varray_ = nullptr;
public:
VMutableArray_For_GVMutableArray(GVMutableArray &varray)
: VMutableArray<T>(varray.size()), varray_(&varray)
{
BLI_assert(varray.type().template is<T>());
}
VMutableArray_For_GVMutableArray(const int64_t size) : VMutableArray<T>(size)
{
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
}
private:
T get_impl(const int64_t index) const override
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
{
T value;
varray_->get(index, &value);
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
return value;
}
void set_impl(const int64_t index, T value) override
{
varray_->set_by_relocate(index, &value);
}
bool is_span_impl() const override
{
return varray_->is_span();
}
Span<T> get_internal_span_impl() const override
{
return varray_->get_internal_span().template typed<T>();
}
bool is_single_impl() const override
{
return varray_->is_single();
}
T get_internal_single_impl() const override
{
T value;
varray_->get_internal_single(&value);
return value;
}
};
/* Used to convert any typed virtual mutable array into a generic one. */
template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableArray {
protected:
VMutableArray<T> *varray_ = nullptr;
public:
GVMutableArray_For_VMutableArray(VMutableArray<T> &varray)
: GVMutableArray(CPPType::get<T>(), varray.size()), varray_(&varray)
{
}
protected:
GVMutableArray_For_VMutableArray(const int64_t size) : GVMutableArray(CPPType::get<T>(), size)
{
}
void get_impl(const int64_t index, void *r_value) const override
{
*(T *)r_value = varray_->get(index);
}
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override
{
new (r_value) T(varray_->get(index));
}
bool is_span_impl() const override
{
return varray_->is_span();
}
GSpan get_internal_span_impl() const override
{
Span<T> span = varray_->get_internal_span();
return span;
}
bool is_single_impl() const override
{
return varray_->is_single();
}
void get_internal_single_impl(void *r_value) const override
{
*(T *)r_value = varray_->get_internal_single();
}
void set_by_copy_impl(const int64_t index, const void *value) override
{
const T &value_ = *(const T *)value;
varray_->set(index, value_);
}
void set_by_relocate_impl(const int64_t index, void *value) override
{
T &value_ = *(T *)value;
varray_->set(index, std::move(value_));
value_.~T();
}
void set_by_move_impl(const int64_t index, void *value) override
{
T &value_ = *(T *)value;
varray_->set(index, std::move(value_));
}
void set_all_impl(const void *src) override
{
varray_->set_all(Span((T *)src, size_));
}
void materialize_impl(const IndexMask mask, void *dst) const override
{
varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override
{
varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size()));
}
const void *try_get_internal_varray_impl() const override
{
return (const VArray<T> *)varray_;
}
void *try_get_internal_mutable_varray_impl() override
{
return varray_;
}
};
/* A generic version of VArray_Span. */
class GVArray_GSpan : public GSpan {
private:
const GVArray &varray_;
void *owned_data_ = nullptr;
public:
GVArray_GSpan(const GVArray &varray);
~GVArray_GSpan();
};
/* A generic version of VMutableArray_Span. */
class GVMutableArray_GSpan : public GMutableSpan {
private:
GVMutableArray &varray_;
void *owned_data_ = nullptr;
bool save_has_been_called_ = false;
bool show_not_saved_warning_ = true;
public:
GVMutableArray_GSpan(GVMutableArray &varray, bool copy_values_to_span = true);
~GVMutableArray_GSpan();
void save();
void disable_not_applied_warning();
};
/* Similar to GVArray_GSpan, but the resulting span is typed. */
template<typename T> class GVArray_Span : public Span<T> {
private:
GVArray_GSpan varray_gspan_;
public:
GVArray_Span(const GVArray &varray) : varray_gspan_(varray)
{
BLI_assert(varray.type().is<T>());
this->data_ = (const T *)varray_gspan_.data();
this->size_ = varray_gspan_.size();
}
};
template<typename T> class GVArray_For_OwnedVArray : public GVArray_For_VArray<T> {
private:
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
VArrayPtr<T> owned_varray_;
public:
/* Takes ownership of varray and passes a reference to the base class. */
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVArray_For_OwnedVArray(VArrayPtr<T> varray)
: GVArray_For_VArray<T>(*varray), owned_varray_(std::move(varray))
{
}
};
template<typename T> class VArray_For_OwnedGVArray : public VArray_For_GVArray<T> {
private:
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVArrayPtr owned_varray_;
public:
/* Takes ownership of varray and passes a reference to the base class. */
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
VArray_For_OwnedGVArray(GVArrayPtr varray)
: VArray_For_GVArray<T>(*varray), owned_varray_(std::move(varray))
{
}
};
template<typename T>
class GVMutableArray_For_OwnedVMutableArray : public GVMutableArray_For_VMutableArray<T> {
private:
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
VMutableArrayPtr<T> owned_varray_;
public:
/* Takes ownership of varray and passes a reference to the base class. */
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVMutableArray_For_OwnedVMutableArray(VMutableArrayPtr<T> varray)
: GVMutableArray_For_VMutableArray<T>(*varray), owned_varray_(std::move(varray))
{
}
};
template<typename T>
class VMutableArray_For_OwnedGVMutableArray : public VMutableArray_For_GVMutableArray<T> {
private:
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVMutableArrayPtr owned_varray_;
public:
/* Takes ownership of varray and passes a reference to the base class. */
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
VMutableArray_For_OwnedGVMutableArray(GVMutableArrayPtr varray)
: VMutableArray_For_GVMutableArray<T>(*varray), owned_varray_(std::move(varray))
{
}
};
/* Utility to embed a typed virtual array into a generic one. This avoids one allocation and give
* the compiler more opportunity to optimize the generic virtual array. */
template<typename T, typename VArrayT>
class GVArray_For_EmbeddedVArray : public GVArray_For_VArray<T> {
private:
VArrayT embedded_varray_;
public:
template<typename... Args>
GVArray_For_EmbeddedVArray(const int64_t size, Args &&...args)
: GVArray_For_VArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
{
this->varray_ = &embedded_varray_;
}
};
/* Same as GVArray_For_EmbeddedVArray, but for mutable virtual arrays. */
template<typename T, typename VMutableArrayT>
class GVMutableArray_For_EmbeddedVMutableArray : public GVMutableArray_For_VMutableArray<T> {
private:
VMutableArrayT embedded_varray_;
public:
template<typename... Args>
GVMutableArray_For_EmbeddedVMutableArray(const int64_t size, Args &&...args)
: GVMutableArray_For_VMutableArray<T>(size), embedded_varray_(std::forward<Args>(args)...)
{
this->varray_ = &embedded_varray_;
}
};
/* Same as VArray_For_ArrayContainer, but for a generic virtual array. */
template<typename Container, typename T = typename Container::value_type>
class GVArray_For_ArrayContainer
: public GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>> {
public:
GVArray_For_ArrayContainer(Container container)
: GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>>(
container.size(), std::move(container))
{
}
};
/* Same as VArray_For_DerivedSpan, but for a generic virtual array. */
template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)>
class GVArray_For_DerivedSpan
: public GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>> {
public:
GVArray_For_DerivedSpan(const Span<StructT> data)
: GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>>(
data.size(), data)
{
}
};
/* Same as VMutableArray_For_DerivedSpan, but for a generic virtual array. */
template<typename StructT,
typename ElemT,
ElemT (*GetFunc)(const StructT &),
void (*SetFunc)(StructT &, ElemT)>
class GVMutableArray_For_DerivedSpan
: public GVMutableArray_For_EmbeddedVMutableArray<
ElemT,
VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>> {
public:
GVMutableArray_For_DerivedSpan(const MutableSpan<StructT> data)
: GVMutableArray_For_EmbeddedVMutableArray<
ElemT,
VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(data.size(), data)
{
}
};
/* Same as VArray_For_Span, but for a generic virtual array. */
template<typename T>
class GVArray_For_Span : public GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>> {
public:
GVArray_For_Span(const Span<T> data)
: GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>>(data.size(), data)
{
}
};
/* Same as VMutableArray_For_MutableSpan, but for a generic virtual array. */
template<typename T>
class GVMutableArray_For_MutableSpan
: public GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>> {
public:
GVMutableArray_For_MutableSpan(const MutableSpan<T> data)
: GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>>(data.size(),
data)
{
}
};
/**
* Utility class to create the "best" typed virtual array for a given generic virtual array.
* In most cases we don't just want to use VArray_For_GVArray, because it adds an additional
* indirection on element-access that can be avoided in many cases (e.g. when the virtual array is
* just a span or single value).
*
* This is not a virtual array itself, but is used to get a virtual array.
*/
template<typename T> class GVArray_Typed {
private:
const VArray<T> *varray_;
/* Of these optional virtual arrays, at most one is constructed at any time. */
std::optional<VArray_For_Span<T>> varray_span_;
std::optional<VArray_For_Single<T>> varray_single_;
std::optional<VArray_For_GVArray<T>> varray_any_;
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVArrayPtr owned_gvarray_;
public:
explicit GVArray_Typed(const GVArray &gvarray)
{
BLI_assert(gvarray.type().is<T>());
if (gvarray.is_span()) {
const GSpan span = gvarray.get_internal_span();
varray_span_.emplace(span.typed<T>());
varray_ = &*varray_span_;
}
else if (gvarray.is_single()) {
T single_value;
gvarray.get_internal_single(&single_value);
varray_single_.emplace(single_value, gvarray.size());
varray_ = &*varray_single_;
}
else if (const VArray<T> *internal_varray = gvarray.try_get_internal_varray<T>()) {
varray_ = internal_varray;
}
else {
varray_any_.emplace(gvarray);
varray_ = &*varray_any_;
}
}
/* Same as the constructor above, but also takes ownership of the passed in virtual array. */
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
explicit GVArray_Typed(GVArrayPtr gvarray) : GVArray_Typed(*gvarray)
{
owned_gvarray_ = std::move(gvarray);
}
const VArray<T> &operator*() const
{
return *varray_;
}
const VArray<T> *operator->() const
{
return varray_;
}
/* Support implicit cast to the typed virtual array for convenience when `varray->typed<T>()` is
* used within an expression. */
operator const VArray<T> &() const
{
return *varray_;
}
T operator[](const int64_t index) const
{
return varray_->get(index);
}
int64_t size() const
{
return varray_->size();
}
IndexRange index_range() const
{
return IndexRange(this->size());
}
};
/* Same as GVArray_Typed, but for mutable virtual arrays. */
template<typename T> class GVMutableArray_Typed {
private:
VMutableArray<T> *varray_;
std::optional<VMutableArray_For_MutableSpan<T>> varray_span_;
std::optional<VMutableArray_For_GVMutableArray<T>> varray_any_;
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
GVMutableArrayPtr owned_gvarray_;
public:
explicit GVMutableArray_Typed(GVMutableArray &gvarray)
{
BLI_assert(gvarray.type().is<T>());
if (gvarray.is_span()) {
const GMutableSpan span = gvarray.get_internal_span();
varray_span_.emplace(span.typed<T>());
varray_ = &*varray_span_;
}
else if (VMutableArray<T> *internal_varray = gvarray.try_get_internal_mutable_varray<T>()) {
varray_ = internal_varray;
}
else {
varray_any_.emplace(gvarray);
varray_ = &*varray_any_;
}
}
Geometry Nodes: use virtual arrays in internal attribute api A virtual array is a data structure that is similar to a normal array in that its elements can be accessed by an index. However, a virtual array does not have to be a contiguous array internally. Instead, its elements can be layed out arbitrarily while element access happens through a virtual function call. However, the virtual array data structures are designed so that the virtual function call can be avoided in cases where it could become a bottleneck. Most commonly, a virtual array is backed by an actual array/span or is a single value internally, that is the same for every index. Besides those, there are many more specialized virtual arrays like the ones that provides vertex positions based on the `MVert` struct or vertex group weights. Not all attributes used by geometry nodes are stored in simple contiguous arrays. To provide uniform access to all kinds of attributes, the attribute API has to provide virtual array functionality that hides the implementation details of attributes. Before this refactor, the attribute API provided its own virtual array implementation as part of the `ReadAttribute` and `WriteAttribute` types. That resulted in unnecessary code duplication with the virtual array system. Even worse, it bound many algorithms used by geometry nodes to the specifics of the attribute API, even though they could also use different data sources (such as data from sockets, default values, later results of expressions, ...). This refactor removes the `ReadAttribute` and `WriteAttribute` types and replaces them with `GVArray` and `GVMutableArray` respectively. The `GV` stands for "generic virtual". The "generic" means that the data type contained in those virtual arrays is only known at run-time. There are the corresponding statically typed types `VArray<T>` and `VMutableArray<T>` as well. No regressions are expected from this refactor. It does come with one improvement for users. The attribute API can convert the data type on write now. This is especially useful when writing to builtin attributes like `material_index` with e.g. the Attribute Math node (which usually just writes to float attributes, while `material_index` is an integer attribute). Differential Revision: https://developer.blender.org/D10994
2021-04-17 16:41:03 +02:00
explicit GVMutableArray_Typed(GVMutableArrayPtr gvarray) : GVMutableArray_Typed(*gvarray)
{
owned_gvarray_ = std::move(gvarray);
}
VMutableArray<T> &operator*()
{
return *varray_;
}
VMutableArray<T> *operator->()
{
return varray_;
}
operator VMutableArray<T> &()
{
return *varray_;
}
T operator[](const int64_t index) const
{
return varray_->get(index);
}
int64_t size() const
{
return varray_->size();
}
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
};
class GVArray_For_SlicedGVArray : public GVArray {
protected:
const GVArray &varray_;
int64_t offset_;
public:
GVArray_For_SlicedGVArray(const GVArray &varray, const IndexRange slice)
: GVArray(varray.type(), slice.size()), varray_(varray), offset_(slice.start())
{
BLI_assert(slice.one_after_last() <= varray.size());
}
/* TODO: Add #materialize method. */
void get_impl(const int64_t index, void *r_value) const override;
void get_to_uninitialized_impl(const int64_t index, void *r_value) const override;
};
/**
* Utility class to create the "best" sliced virtual array.
*/
class GVArray_Slice {
private:
const GVArray *varray_;
/* Of these optional virtual arrays, at most one is constructed at any time. */
std::optional<GVArray_For_GSpan> varray_span_;
std::optional<GVArray_For_SlicedGVArray> varray_any_;
public:
GVArray_Slice(const GVArray &varray, const IndexRange slice);
const GVArray &operator*()
{
return *varray_;
}
const GVArray *operator->()
{
return varray_;
}
operator const GVArray &()
{
return *varray_;
}
};
Functions: refactor virtual array data structures When a function is executed for many elements (e.g. per point) it is often the case that some parameters are different for every element and other parameters are the same (there are some more less common cases). To simplify writing such functions one can use a "virtual array". This is a data structure that has a value for every index, but might not be stored as an actual array internally. Instead, it might be just a single value or is computed on the fly. There are various tradeoffs involved when using this data structure which are mentioned in `BLI_virtual_array.hh`. It is called "virtual", because it uses inheritance and virtual methods. Furthermore, there is a new virtual vector array data structure, which is an array of vectors. Both these types have corresponding generic variants, which can be used when the data type is not known at compile time. This is typically the case when building a somewhat generic execution system. The function system used these virtual data structures before, but now they are more versatile. I've done this refactor in preparation for the attribute processor and other features of geometry nodes. I moved the typed virtual arrays to blenlib, so that they can be used independent of the function system. One open question for me is whether all the generic data structures (and `CPPType`) should be moved to blenlib as well. They are well isolated and don't really contain any business logic. That can be done later if necessary.
2021-03-21 19:31:24 +01:00
} // namespace blender::fn