Allow ArrayHandle to have a runtime selectable number of buffers

Previously, the number of buffers held by an `ArrayHandle` had to be
determined statically at compile time by the storage. Most of the time
this is fine. However, there are some exceptions where the number of
buffers need to be selected at runtime. For example, the
`ArrayHandleRecombineVec` does not specify the number of components it
uses, and it needed a hack where it stored buffers in the metadata of
another buffer, which is bad.

This change allows the number of buffers to vary at runtime (at least at
construction). The buffers were already managed in a `std::vector`. It
now no longer forces the vector to be a specific size.
`GetNumberOfBuffers` was removed from the `Storage`. Instead, if the
number of buffers was not specified at construction, an allocation of
size 0 is done to create default buffers.

The biggest change is to the interface of the storage object methods,
which now take `std::vector` instead of pointers to `Buffer` objects.
This adds a little hastle in having to copy subsets of this `vector`
when a storage object has multiple sub-arrays. But it does simplify some
of the templating.
This commit is contained in:
Kenneth Moreland 2022-06-28 14:26:38 -06:00
parent 5488a08987
commit 05f144eb19
32 changed files with 872 additions and 720 deletions

@ -0,0 +1,30 @@
# Allow ArrayHandle to have a runtime selectable number of buffers
Previously, the number of buffers held by an `ArrayHandle` had to be
determined statically at compile time by the storage. Most of the time this
is fine. However, there are some exceptions where the number of buffers
need to be selected at runtime. For example, the `ArrayHandleRecombineVec`
does not specify the number of components it uses, and it needed a hack
where it stored buffers in the metadata of another buffer, which is bad.
This change allows the number of buffers to vary at runtime (at least at
construction). The buffers were already managed in a `std::vector`. It now
no longer forces the vector to be a specific size. `GetNumberOfBuffers` was
removed from the `Storage`. Instead, if the number of buffers was not
specified at construction, an allocation of size 0 is done to create
default buffers.
The biggest change is to the interface of the storage object methods, which
now take `std::vector` instead of pointers to `Buffer` objects. This adds a
little hassle in having to copy subsets of this `vector` when a storage
object has multiple sub-arrays. But it does simplify some of the
templating.
Other changes to the `Storage` structure include requiring all objects to
include a `CreateBuffers` method that accepts no arguments. This method
will be used by `ArrayHandle` in its default constructor. Previously,
`ArrayHandle` would create the `vector` of `Buffer` objects itself, but it
now must call this method in the `Storage` to do this. (It also has a nice
side effect of allowing the `Storage` to initialize the buffer objects if
necessary. Another change was to remove the `GetNumberOfBuffers` method
(which no longer has meaning).

@ -314,7 +314,7 @@ public:
/// Constructs an empty ArrayHandle. /// Constructs an empty ArrayHandle.
/// ///
VTKM_CONT ArrayHandle() VTKM_CONT ArrayHandle()
: Buffers(static_cast<std::size_t>(StorageType::GetNumberOfBuffers())) : Buffers(StorageType::CreateBuffers())
{ {
} }
@ -349,17 +349,10 @@ public:
VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers) VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
: Buffers(buffers) : Buffers(buffers)
{ {
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
} }
VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
: Buffers(std::move(buffers)) : Buffers(std::move(buffers))
{
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
}
VTKM_CONT ArrayHandle(const vtkm::cont::internal::Buffer* buffers)
: Buffers(buffers, buffers + StorageType::GetNumberOfBuffers())
{ {
} }
///@} ///@}
@ -420,9 +413,10 @@ public:
return true; // different valuetype and/or storage return true; // different valuetype and/or storage
} }
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() VTKM_DEPRECATED(1.9, "Use the size of the std::vector returned from GetBuffers.")
VTKM_CONT constexpr vtkm::IdComponent GetNumberOfBuffers()
{ {
return StorageType::GetNumberOfBuffers(); return static_cast<vtkm::IdComponent>(this->GetBuffers().size());
} }
/// Get the storage. /// Get the storage.
@ -776,9 +770,15 @@ public:
} }
} }
/// Returns the internal `Buffer` structures that hold the data. /// \brief Returns the internal `Buffer` structures that hold the data.
/// ///
VTKM_CONT vtkm::cont::internal::Buffer* GetBuffers() const { return this->Buffers.data(); } /// Note that great care should be taken when modifying buffers outside of the ArrayHandle.
///
VTKM_CONT const std::vector<vtkm::cont::internal::Buffer>& GetBuffers() const
{
return this->Buffers;
}
VTKM_CONT std::vector<vtkm::cont::internal::Buffer>& GetBuffers() { return this->Buffers; }
private: private:
mutable std::vector<vtkm::cont::internal::Buffer> Buffers; mutable std::vector<vtkm::cont::internal::Buffer> Buffers;
@ -789,11 +789,13 @@ protected:
this->Buffers[static_cast<std::size_t>(index)] = buffer; this->Buffers[static_cast<std::size_t>(index)] = buffer;
} }
// BufferContainer must be an iteratable container of Buffer objects. VTKM_CONT void SetBuffers(const std::vector<vtkm::cont::internal::Buffer>& buffers)
template <typename BufferContainer>
VTKM_CONT void SetBuffers(const BufferContainer& buffers)
{ {
std::copy(buffers.begin(), buffers.end(), this->Iterators->Buffers.begin()); this->Buffers = buffers;
}
VTKM_CONT void SetBuffers(std::vector<vtkm::cont::internal::Buffer>&& buffers)
{
this->Buffers = std::move(buffers);
} }
}; };
@ -915,6 +917,25 @@ namespace internal
namespace detail namespace detail
{ {
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>&);
template <typename T, typename S, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const vtkm::cont::ArrayHandle<T, S>& array,
const Args&... args);
template <typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const vtkm::cont::internal::Buffer& buffer,
const Args&... args);
template <typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const std::vector<vtkm::cont::internal::Buffer>& addbuffs,
const Args&... args);
template <typename Arg0, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const Arg0& arg0,
const Args&... args);
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>&) VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>&)
{ {
// Nothing left to add. // Nothing left to add.
@ -925,9 +946,7 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
const vtkm::cont::ArrayHandle<T, S>& array, const vtkm::cont::ArrayHandle<T, S>& array,
const Args&... args) const Args&... args)
{ {
vtkm::cont::internal::Buffer* arrayBuffers = array.GetBuffers(); CreateBuffersImpl(buffers, array.GetBuffers(), args...);
buffers.insert(buffers.end(), arrayBuffers, arrayBuffers + array.GetNumberOfBuffers());
CreateBuffersImpl(buffers, args...);
} }
template <typename... Args> template <typename... Args>
@ -948,11 +967,6 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
CreateBuffersImpl(buffers, args...); CreateBuffersImpl(buffers, args...);
} }
template <typename Arg0, typename... Args>
VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer>& buffers,
const Arg0& arg0,
const Args&... args);
template <typename T, typename S, typename... Args> template <typename T, typename S, typename... Args>
VTKM_CONT inline void CreateBuffersResolveArrays(std::vector<vtkm::cont::internal::Buffer>& buffers, VTKM_CONT inline void CreateBuffersResolveArrays(std::vector<vtkm::cont::internal::Buffer>& buffers,
std::true_type, std::true_type,
@ -1001,7 +1015,7 @@ VTKM_CONT inline void CreateBuffersImpl(std::vector<vtkm::cont::internal::Buffer
/// - `ArrayHandle`: The buffers from the `ArrayHandle` are added to the list. /// - `ArrayHandle`: The buffers from the `ArrayHandle` are added to the list.
/// - `Buffer`: A copy of the buffer is added to the list. /// - `Buffer`: A copy of the buffer is added to the list.
/// - `std::vector<Buffer>`: A copy of all buffers in this vector are added to the list. /// - `std::vector<Buffer>`: A copy of all buffers in this vector are added to the list.
/// - Anything else: A buffer with the given object attached as metadata is /// - Anything else: A buffer with the given object attached as metadata is added to the list.
/// ///
template <typename... Args> template <typename... Args>
VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const Args&... args) VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const Args&... args)

@ -35,10 +35,13 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalBasicRead<T>; using ReadPortalType = vtkm::internal::ArrayPortalBasicRead<T>;
using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>; using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(1);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -46,36 +49,43 @@ public:
vtkm::internal::NumberOfValuesToNumberOfBytes<T>(numValues), preserve, token); vtkm::internal::NumberOfValuesToNumberOfBytes<T>(numValues), preserve, token);
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return static_cast<vtkm::Id>(buffers->GetNumberOfBytes() / VTKM_ASSERT(buffers.size() == 1);
return static_cast<vtkm::Id>(buffers[0].GetNumberOfBytes() /
static_cast<vtkm::BufferSizeType>(sizeof(T))); static_cast<vtkm::BufferSizeType>(sizeof(T)));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue, const T& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
constexpr vtkm::BufferSizeType fillValueSize = constexpr vtkm::BufferSizeType fillValueSize =
static_cast<vtkm::BufferSizeType>(sizeof(fillValue)); static_cast<vtkm::BufferSizeType>(sizeof(fillValue));
buffers[0].Fill( buffers[0].Fill(
&fillValue, fillValueSize, startIndex * fillValueSize, endIndex * fillValueSize, token); &fillValue, fillValueSize, startIndex * fillValueSize, endIndex * fillValueSize, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
return ReadPortalType(reinterpret_cast<const T*>(buffers[0].ReadPointerDevice(device, token)), return ReadPortalType(reinterpret_cast<const T*>(buffers[0].ReadPointerDevice(device, token)),
GetNumberOfValues(buffers)); GetNumberOfValues(buffers));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
return WritePortalType(reinterpret_cast<T*>(buffers[0].WritePointerDevice(device, token)), return WritePortalType(reinterpret_cast<T*>(buffers[0].WritePointerDevice(device, token)),
GetNumberOfValues(buffers)); GetNumberOfValues(buffers));
} }
@ -345,7 +355,8 @@ struct Serialization<vtkm::cont::ArrayHandleBasic<T>>
vtkm::cont::internal::Buffer buffer; vtkm::cont::internal::Buffer buffer;
vtkmdiy::load(bb, buffer); vtkmdiy::load(bb, buffer);
obj = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(&buffer); obj = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(
vtkm::cont::internal::CreateBuffers(buffer));
} }
}; };

@ -82,10 +82,13 @@ public:
using ReadPortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalConstType>; using ReadPortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalConstType>;
using WritePortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalType>; using WritePortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(1);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numberOfBits, VTKM_CONT static void ResizeBuffers(vtkm::Id numberOfBits,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -102,20 +105,23 @@ public:
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits = numberOfBits; buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits = numberOfBits;
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits = vtkm::Id numberOfBits =
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits; buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits;
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits); VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
return numberOfBits; return numberOfBits;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
bool fillValue, bool fillValue,
vtkm::Id startBit, vtkm::Id startBit,
vtkm::Id endBit, vtkm::Id endBit,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
constexpr vtkm::BufferSizeType wordTypeSize = constexpr vtkm::BufferSizeType wordTypeSize =
static_cast<vtkm::BufferSizeType>(sizeof(WordType)); static_cast<vtkm::BufferSizeType>(sizeof(WordType));
constexpr vtkm::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT; constexpr vtkm::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT;
@ -141,10 +147,12 @@ public:
} }
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits = GetNumberOfValues(buffers); vtkm::Id numberOfBits = GetNumberOfValues(buffers);
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits); VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
@ -152,10 +160,12 @@ public:
BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits)); BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
} }
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
VTKM_ASSERT(buffers.size() == 1);
vtkm::Id numberOfBits = GetNumberOfValues(buffers); vtkm::Id numberOfBits = GetNumberOfValues(buffers);
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits); VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);

@ -17,6 +17,8 @@
#include <vtkm/cont/ErrorBadAllocation.h> #include <vtkm/cont/ErrorBadAllocation.h>
#include <vtkm/cont/Token.h> #include <vtkm/cont/Token.h>
#include <array>
namespace vtkm namespace vtkm
{ {
namespace internal namespace internal
@ -199,26 +201,27 @@ struct ArrayHandleCartesianProductTraits
template <typename T, typename ST1, typename ST2, typename ST3> template <typename T, typename ST1, typename ST2, typename ST3>
class Storage<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>> class Storage<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>>
{ {
struct Info
{
std::array<std::size_t, 4> BufferOffset;
};
using Storage1 = vtkm::cont::internal::Storage<T, ST1>; using Storage1 = vtkm::cont::internal::Storage<T, ST1>;
using Storage2 = vtkm::cont::internal::Storage<T, ST2>; using Storage2 = vtkm::cont::internal::Storage<T, ST2>;
using Storage3 = vtkm::cont::internal::Storage<T, ST3>; using Storage3 = vtkm::cont::internal::Storage<T, ST3>;
template <typename Buffs> using Array1 = vtkm::cont::ArrayHandle<T, ST1>;
VTKM_CONT constexpr static Buffs* Buffers1(Buffs* buffers) using Array2 = vtkm::cont::ArrayHandle<T, ST2>;
{ using Array3 = vtkm::cont::ArrayHandle<T, ST3>;
return buffers;
}
template <typename Buffs> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> GetBuffers(
VTKM_CONT constexpr static Buffs* Buffers2(Buffs* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers,
std::size_t subArray)
{ {
return buffers + Storage1::GetNumberOfBuffers(); Info info = buffers[0].GetMetaData<Info>();
} return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() +
info.BufferOffset[subArray - 1],
template <typename Buffs> buffers.begin() + info.BufferOffset[subArray]);
VTKM_CONT constexpr static Buffs* Buffers3(Buffs* buffers)
{
return buffers + Storage1::GetNumberOfBuffers() + Storage2::GetNumberOfBuffers();
} }
public: public:
@ -235,20 +238,15 @@ public:
typename Storage2::WritePortalType, typename Storage2::WritePortalType,
typename Storage3::WritePortalType>; typename Storage3::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return Storage1::GetNumberOfBuffers() + Storage2::GetNumberOfBuffers() + return (Storage1::GetNumberOfValues(GetBuffers(buffers, 1)) *
Storage3::GetNumberOfBuffers(); Storage2::GetNumberOfValues(GetBuffers(buffers, 2)) *
Storage3::GetNumberOfValues(GetBuffers(buffers, 3)));
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
{
return (Storage1::GetNumberOfValues(Buffers1(buffers)) *
Storage2::GetNumberOfValues(Buffers2(buffers)) *
Storage3::GetNumberOfValues(Buffers3(buffers)));
}
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers,
const vtkm::Vec<T, 3>& fillValue, const vtkm::Vec<T, 3>& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -259,46 +257,63 @@ public:
throw vtkm::cont::ErrorBadValue( throw vtkm::cont::ErrorBadValue(
"Fill for ArrayHandleCartesianProduct can only be used to fill entire array."); "Fill for ArrayHandleCartesianProduct can only be used to fill entire array.");
} }
Storage1::Fill( auto subBuffers = GetBuffers(buffers, 1);
Buffers1(buffers), fillValue[0], 0, Storage1::GetNumberOfValues(Buffers1(buffers)), token); Storage1::Fill(subBuffers, fillValue[0], 0, Storage1::GetNumberOfValues(subBuffers), token);
Storage2::Fill( subBuffers = GetBuffers(buffers, 2);
Buffers2(buffers), fillValue[1], 0, Storage2::GetNumberOfValues(Buffers2(buffers)), token); Storage2::Fill(subBuffers, fillValue[1], 0, Storage2::GetNumberOfValues(subBuffers), token);
Storage3::Fill( subBuffers = GetBuffers(buffers, 3);
Buffers3(buffers), fillValue[2], 0, Storage3::GetNumberOfValues(Buffers3(buffers)), token); Storage3::Fill(subBuffers, fillValue[2], 0, Storage3::GetNumberOfValues(subBuffers), token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(Storage1::CreateReadPortal(Buffers1(buffers), device, token), return ReadPortalType(Storage1::CreateReadPortal(GetBuffers(buffers, 1), device, token),
Storage2::CreateReadPortal(Buffers2(buffers), device, token), Storage2::CreateReadPortal(GetBuffers(buffers, 2), device, token),
Storage3::CreateReadPortal(Buffers3(buffers), device, token)); Storage3::CreateReadPortal(GetBuffers(buffers, 3), device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(Storage1::CreateWritePortal(Buffers1(buffers), device, token), return WritePortalType(Storage1::CreateWritePortal(GetBuffers(buffers, 1), device, token),
Storage2::CreateWritePortal(Buffers2(buffers), device, token), Storage2::CreateWritePortal(GetBuffers(buffers, 2), device, token),
Storage3::CreateWritePortal(Buffers3(buffers), device, token)); Storage3::CreateWritePortal(GetBuffers(buffers, 3), device, token));
} }
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST1> GetArrayHandle1( VTKM_CONT static Array1 GetArrayHandle1(const std::vector<vtkm::cont::internal::Buffer>& buffers)
const vtkm::cont::internal::Buffer* buffers)
{ {
return vtkm::cont::ArrayHandle<T, ST1>(Buffers1(buffers)); return Array1(GetBuffers(buffers, 1));
} }
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST2> GetArrayHandle2( VTKM_CONT static Array2 GetArrayHandle2(const std::vector<vtkm::cont::internal::Buffer>& buffers)
const vtkm::cont::internal::Buffer* buffers)
{ {
return vtkm::cont::ArrayHandle<T, ST2>(Buffers2(buffers)); return Array2(GetBuffers(buffers, 2));
} }
VTKM_CONT static vtkm::cont::ArrayHandle<T, ST3> GetArrayHandle3( VTKM_CONT static Array3 GetArrayHandle3(const std::vector<vtkm::cont::internal::Buffer>& buffers)
const vtkm::cont::internal::Buffer* buffers)
{ {
return vtkm::cont::ArrayHandle<T, ST3>(Buffers3(buffers)); return Array3(GetBuffers(buffers, 3));
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const Array1& array1 = Array1{},
const Array2& array2 = Array2{},
const Array3& array3 = Array3{})
{
const std::vector<vtkm::cont::internal::Buffer>& buffers1 = array1.GetBuffers();
const std::vector<vtkm::cont::internal::Buffer>& buffers2 = array2.GetBuffers();
const std::vector<vtkm::cont::internal::Buffer>& buffers3 = array3.GetBuffers();
Info info;
info.BufferOffset[0] = 1;
info.BufferOffset[1] = info.BufferOffset[0] + buffers1.size();
info.BufferOffset[2] = info.BufferOffset[1] + buffers2.size();
info.BufferOffset[3] = info.BufferOffset[2] + buffers3.size();
return vtkm::cont::internal::CreateBuffers(info, buffers1, buffers2, buffers3);
} }
}; };
} // namespace internal } // namespace internal
@ -335,7 +350,7 @@ public:
ArrayHandleCartesianProduct(const FirstHandleType& firstArray, ArrayHandleCartesianProduct(const FirstHandleType& firstArray,
const SecondHandleType& secondArray, const SecondHandleType& secondArray,
const ThirdHandleType& thirdArray) const ThirdHandleType& thirdArray)
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray, thirdArray)) : Superclass(StorageType::CreateBuffers(firstArray, secondArray, thirdArray))
{ {
} }

@ -20,6 +20,7 @@
#include <vtkmstd/integer_sequence.h> #include <vtkmstd/integer_sequence.h>
#include <numeric>
#include <type_traits> #include <type_traits>
namespace vtkm namespace vtkm
@ -169,31 +170,6 @@ struct VerifyArrayHandle
"must be a list of ArrayHandle types."); "must be a list of ArrayHandle types.");
}; };
template <std::size_t I>
struct BufferIndexImpl
{
template <typename... Ts>
static constexpr vtkm::IdComponent Value(vtkm::IdComponent n, Ts... remaining)
{
return n + BufferIndexImpl<I - 1>::Value(remaining...);
}
};
template <>
struct BufferIndexImpl<0>
{
template <typename... Ts>
static constexpr vtkm::IdComponent Value(Ts...)
{
return 0;
}
};
template <std::size_t I, typename... StorageTypes>
constexpr vtkm::IdComponent BufferIndex()
{
return BufferIndexImpl<I>::Value(StorageTypes::GetNumberOfBuffers()...);
}
} // end namespace compvec } // end namespace compvec
} // namespace internal } // namespace internal
@ -226,21 +202,31 @@ class Storage<vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags)
{ {
using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>; using ValueType = vtkm::Vec<T, static_cast<vtkm::IdComponent>(sizeof...(StorageTags))>;
struct Info
{
std::array<std::size_t, sizeof...(StorageTags) + 1> BufferOffset;
};
template <typename S> template <typename S>
using StorageFor = vtkm::cont::internal::Storage<T, S>; using StorageFor = vtkm::cont::internal::Storage<T, S>;
using StorageTuple = vtkm::Tuple<StorageFor<StorageTags>...>; using StorageTuple = vtkm::Tuple<StorageFor<StorageTags>...>;
template <std::size_t I> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> GetBuffers(
VTKM_CONT static constexpr vtkm::IdComponent BufferIndex() const std::vector<vtkm::cont::internal::Buffer>& buffers,
std::size_t subArray)
{ {
return compvec::BufferIndex<I, StorageFor<StorageTags>...>(); Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.BufferOffset[subArray],
buffers.begin() +
info.BufferOffset[subArray + 1]);
} }
template <std::size_t I, typename Buff> template <std::size_t I>
VTKM_CONT static Buff* Buffers(Buff* buffers) VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + BufferIndex<I>(); return GetBuffers(buffers, I);
} }
using IndexList = vtkmstd::make_index_sequence<sizeof...(StorageTags)>; using IndexList = vtkmstd::make_index_sequence<sizeof...(StorageTags)>;
@ -255,19 +241,21 @@ private:
template <std::size_t... Is> template <std::size_t... Is>
static void ResizeBuffersImpl(vtkmstd::index_sequence<Is...>, static void ResizeBuffersImpl(vtkmstd::index_sequence<Is...>,
vtkm::Id numValues, vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
std::vector<std::vector<vtkm::cont::internal::Buffer>> bufferPartitions = { Buffers<Is>(
buffers)... };
auto init_list = { (vtkm::tuple_element_t<Is, StorageTuple>::ResizeBuffers( auto init_list = { (vtkm::tuple_element_t<Is, StorageTuple>::ResizeBuffers(
numValues, Buffers<Is>(buffers), preserve, token), numValues, bufferPartitions[Is], preserve, token),
false)... }; false)... };
(void)init_list; (void)init_list;
} }
template <std::size_t... Is> template <std::size_t... Is>
static void FillImpl(vtkmstd::index_sequence<Is...>, static void FillImpl(vtkmstd::index_sequence<Is...>,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -284,45 +272,43 @@ private:
} }
template <std::size_t... Is> template <std::size_t... Is>
static ReadPortalType CreateReadPortalImpl(vtkmstd::index_sequence<Is...>, static ReadPortalType CreateReadPortalImpl(
const vtkm::cont::internal::Buffer* buffers, vtkmstd::index_sequence<Is...>,
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateReadPortal( return ReadPortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateReadPortal(
Buffers<Is>(buffers), device, token)...); Buffers<Is>(buffers), device, token)...);
} }
template <std::size_t... Is> template <std::size_t... Is>
static WritePortalType CreateWritePortalImpl(vtkmstd::index_sequence<Is...>, static WritePortalType CreateWritePortalImpl(
vtkm::cont::internal::Buffer* buffers, vtkmstd::index_sequence<Is...>,
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateWritePortal( return WritePortalType(vtkm::tuple_element_t<Is, StorageTuple>::CreateWritePortal(
Buffers<Is>(buffers), device, token)...); Buffers<Is>(buffers), device, token)...);
} }
public: public:
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return BufferIndex<sizeof...(StorageTags)>(); return vtkm::TupleElement<0, StorageTuple>::GetNumberOfValues(Buffers<0>(buffers));
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return vtkm::TupleElement<0, StorageTuple>::GetNumberOfValues(buffers);
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
ResizeBuffersImpl(IndexList{}, numValues, buffers, preserve, token); ResizeBuffersImpl(IndexList{}, numValues, buffers, preserve, token);
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -331,65 +317,51 @@ public:
FillImpl(IndexList{}, buffers, fillValue, startIndex, endIndex, token); FillImpl(IndexList{}, buffers, fillValue, startIndex, endIndex, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return CreateReadPortalImpl(IndexList{}, buffers, device, token); return CreateReadPortalImpl(IndexList{}, buffers, device, token);
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return CreateWritePortalImpl(IndexList{}, buffers, device, token); return CreateWritePortalImpl(IndexList{}, buffers, device, token);
} }
private:
template <typename ArrayType>
VTKM_CONT static bool CopyBuffers(const ArrayType& array,
vtkm::cont::internal::Buffer* destBuffers)
{
vtkm::IdComponent numBuffers = array.GetNumberOfBuffers();
const vtkm::cont::internal::Buffer* srcBuffers = array.GetBuffers();
for (vtkm::IdComponent buffIndex = 0; buffIndex < numBuffers; ++buffIndex)
{
destBuffers[buffIndex] = srcBuffers[buffIndex];
}
return false; // Return value does not matter. Hopefully just thrown away by compiler.
}
template <std::size_t... Is, typename... ArrayTs>
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffersImpl(
vtkmstd::index_sequence<Is...>,
const ArrayTs... arrays)
{
std::vector<vtkm::cont::internal::Buffer> buffers(
static_cast<std::size_t>(GetNumberOfBuffers()));
auto init_list = { CopyBuffers(arrays, Buffers<Is>(&buffers.front()))... };
(void)init_list;
return buffers;
}
public: public:
template <typename... ArrayTs> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayTs... arrays) const vtkm::cont::ArrayHandle<T, StorageTags>&... arrays)
{ {
return CreateBuffersImpl(IndexList{}, arrays...); auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
Info info;
std::partial_sum(numBuffers.begin(), numBuffers.end(), info.BufferOffset.begin());
return vtkm::cont::internal::CreateBuffers(info, arrays...);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(vtkm::cont::ArrayHandle<T, StorageTags>{}...);
} }
private: private:
using ArrayTupleType = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>; using ArrayTupleType = vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTags>...>;
template <std::size_t... Is> template <std::size_t... Is>
VTKM_CONT static ArrayTupleType GetArrayTupleImpl(vtkmstd::index_sequence<Is...>, VTKM_CONT static ArrayTupleType GetArrayTupleImpl(
const vtkm::cont::internal::Buffer* buffers) vtkmstd::index_sequence<Is...>,
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return ArrayTupleType(vtkm::cont::ArrayHandle<T, StorageTags>(Buffers<Is>(buffers))...); return ArrayTupleType(vtkm::cont::ArrayHandle<T, StorageTags>(Buffers<Is>(buffers))...);
} }
public: public:
VTKM_CONT static ArrayTupleType GetArrayTuple(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ArrayTupleType GetArrayTuple(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return GetArrayTupleImpl(IndexList{}, buffers); return GetArrayTupleImpl(IndexList{}, buffers);
} }
@ -400,13 +372,13 @@ template <typename T, typename StorageTag>
struct Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : Storage<T, StorageTag> struct Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : Storage<T, StorageTag>
{ {
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::ArrayHandle<T, StorageTag>& array) const vtkm::cont::ArrayHandle<T, StorageTag>& array = vtkm::cont::ArrayHandle<T, StorageTag>{})
{ {
return vtkm::cont::internal::CreateBuffers(array); return vtkm::cont::internal::CreateBuffers(array);
} }
VTKM_CONT static vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTag>> GetArrayTuple( VTKM_CONT static vtkm::Tuple<vtkm::cont::ArrayHandle<T, StorageTag>> GetArrayTuple(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<T, StorageTag>(buffers); return vtkm::cont::ArrayHandle<T, StorageTag>(buffers);
} }

@ -169,16 +169,26 @@ class Storage<T, StorageTagConcatenate<ST1, ST2>>
using ArrayHandleType1 = typename detail::ConcatinateTypeArg<T, ST1>::ArrayHandle; using ArrayHandleType1 = typename detail::ConcatinateTypeArg<T, ST1>::ArrayHandle;
using ArrayHandleType2 = typename detail::ConcatinateTypeArg<T, ST2>::ArrayHandle; using ArrayHandleType2 = typename detail::ConcatinateTypeArg<T, ST2>::ArrayHandle;
template <typename Buff> struct Info
VTKM_CONT static Buff* Buffers1(Buff* buffers)
{ {
return buffers; std::size_t NumBuffers1;
std::size_t NumBuffers2;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers1(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + 1 + info.NumBuffers1);
} }
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> Buffers2(
VTKM_CONT static Buff* Buffers2(Buff* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + SourceStorage1::GetNumberOfBuffers(); Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1 + info.NumBuffers1,
buffers.end());
} }
public: public:
@ -191,18 +201,14 @@ public:
vtkm::internal::ArrayPortalConcatenate<typename SourceStorage1::WritePortalType, vtkm::internal::ArrayPortalConcatenate<typename SourceStorage1::WritePortalType,
typename SourceStorage2::WritePortalType>; typename SourceStorage2::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return (SourceStorage1::GetNumberOfBuffers() + SourceStorage2::GetNumberOfBuffers());
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return (SourceStorage1::GetNumberOfValues(Buffers1(buffers)) + return (SourceStorage1::GetNumberOfValues(Buffers1(buffers)) +
SourceStorage2::GetNumberOfValues(Buffers2(buffers))); SourceStorage2::GetNumberOfValues(Buffers2(buffers)));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue, const T& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -225,35 +231,42 @@ public:
} }
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(SourceStorage1::CreateReadPortal(Buffers1(buffers), device, token), return ReadPortalType(SourceStorage1::CreateReadPortal(Buffers1(buffers), device, token),
SourceStorage2::CreateReadPortal(Buffers2(buffers), device, token)); SourceStorage2::CreateReadPortal(Buffers2(buffers), device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(SourceStorage1::CreateWritePortal(Buffers1(buffers), device, token), return WritePortalType(SourceStorage1::CreateWritePortal(Buffers1(buffers), device, token),
SourceStorage2::CreateWritePortal(Buffers2(buffers), device, token)); SourceStorage2::CreateWritePortal(Buffers2(buffers), device, token));
} }
VTKM_CONT static auto CreateBuffers(const ArrayHandleType1& array1, VTKM_CONT static auto CreateBuffers(const ArrayHandleType1& array1 = ArrayHandleType1{},
const ArrayHandleType2& array2) const ArrayHandleType2& array2 = ArrayHandleType2{})
-> decltype(vtkm::cont::internal::CreateBuffers()) -> decltype(vtkm::cont::internal::CreateBuffers())
{ {
return vtkm::cont::internal::CreateBuffers(array1, array2); Info info;
info.NumBuffers1 = array1.GetBuffers().size();
info.NumBuffers2 = array2.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, array1, array2);
} }
VTKM_CONT static const ArrayHandleType1 GetArray1(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static const ArrayHandleType1 GetArray1(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return ArrayHandleType1(Buffers1(buffers)); return ArrayHandleType1(Buffers1(buffers));
} }
VTKM_CONT static const ArrayHandleType2 GetArray2(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static const ArrayHandleType2 GetArray2(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return ArrayHandleType2(Buffers2(buffers)); return ArrayHandleType2(Buffers2(buffers));
} }

@ -24,6 +24,7 @@
#include <vtkmstd/integer_sequence.h> #include <vtkmstd/integer_sequence.h>
#include <numeric>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@ -306,35 +307,22 @@ using GetWritePortalList =
std::declval<vtkm::cont::DeviceAdapterId>(), std::declval<vtkm::cont::DeviceAdapterId>(),
std::declval<vtkm::cont::Token&>())))...>; std::declval<vtkm::cont::Token&>())))...>;
template <vtkm::IdComponent I, typename ArrayTupleType> template <typename DecoratorImplT, std::size_t NumArrays>
struct BufferIndexImpl
{
static constexpr vtkm::IdComponent Value()
{
return BufferIndexImpl<I - 1, ArrayTupleType>::Value() +
vtkm::TupleElement<I - 1, ArrayTupleType>::GetNumberOfBuffers();
}
};
template <typename ArrayTupleType>
struct BufferIndexImpl<0, ArrayTupleType>
{
static constexpr vtkm::IdComponent Value()
{
// One buffer reserved for metadata.
return 1;
}
};
template <typename DecoratorImplT>
struct DecoratorMetaData struct DecoratorMetaData
{ {
DecoratorImplT Implementation; DecoratorImplT Implementation;
vtkm::Id NumberOfValues = 0; vtkm::Id NumberOfValues = 0;
std::array<std::size_t, NumArrays + 1> BufferOffsets;
DecoratorMetaData(const DecoratorImplT& implementation, vtkm::Id numValues) template <typename... ArrayTs>
DecoratorMetaData(const DecoratorImplT& implementation,
vtkm::Id numValues,
const ArrayTs... arrays)
: Implementation(implementation) : Implementation(implementation)
, NumberOfValues(numValues) , NumberOfValues(numValues)
{ {
auto numBuffers = { std::size_t{ 1 }, arrays.GetBuffers().size()... };
std::partial_sum(numBuffers.begin(), numBuffers.end(), this->BufferOffsets.begin());
} }
DecoratorMetaData() = default; DecoratorMetaData() = default;
@ -363,26 +351,22 @@ struct DecoratorStorageTraits
// size_t integral constants that index ArrayTs: // size_t integral constants that index ArrayTs:
using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>; using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>;
// Returns the index into the buffers array for the array at the given index. using MetaData = DecoratorMetaData<DecoratorImplT, sizeof...(ArrayTs)>;
template <vtkm::IdComponent I>
static constexpr vtkm::IdComponent BufferIndex() static MetaData& GetMetaData(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return BufferIndexImpl<I, ArrayTupleType>::Value(); return buffers[0].GetMetaData<MetaData>();
} }
// Converts a buffers array to the ArrayHandle at the given index. // Converts a buffers array to the ArrayHandle at the given index.
template <vtkm::IdComponent I> template <vtkm::IdComponent I>
static vtkm::TupleElement<I, ArrayTupleType> BuffersToArray( static vtkm::TupleElement<I, ArrayTupleType> BuffersToArray(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::TupleElement<I, ArrayTupleType>(buffers + BufferIndex<I>()); const MetaData& metaData = GetMetaData(buffers);
} std::vector<vtkm::cont::internal::Buffer> subBuffers(
buffers.begin() + metaData.BufferOffsets[I], buffers.begin() + metaData.BufferOffsets[I + 1]);
using MetaData = DecoratorMetaData<DecoratorImplT>; return vtkm::TupleElement<I, ArrayTupleType>(std::move(subBuffers));
static MetaData& GetMetaData(const vtkm::cont::internal::Buffer* buffers)
{
return buffers[0].GetMetaData<MetaData>();
} }
// true_type/false_type depending on whether the decorator supports Allocate: // true_type/false_type depending on whether the decorator supports Allocate:
@ -440,7 +424,7 @@ struct DecoratorStorageTraits
// Static dispatch for calling AllocateSourceArrays on supported implementations: // Static dispatch for calling AllocateSourceArrays on supported implementations:
VTKM_CONT [[noreturn]] static void CallAllocate(std::false_type, VTKM_CONT [[noreturn]] static void CallAllocate(std::false_type,
vtkm::Id, vtkm::Id,
vtkm::cont::internal::Buffer*, const std::vector<vtkm::cont::internal::Buffer>&,
vtkm::CopyFlag, vtkm::CopyFlag,
vtkm::cont::Token&, vtkm::cont::Token&,
ArrayTs...) ArrayTs...)
@ -450,7 +434,7 @@ struct DecoratorStorageTraits
VTKM_CONT static void CallAllocate(std::true_type, VTKM_CONT static void CallAllocate(std::true_type,
vtkm::Id newSize, vtkm::Id newSize,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token, vtkm::cont::Token& token,
ArrayTs... arrays) ArrayTs... arrays)
@ -463,11 +447,12 @@ struct DecoratorStorageTraits
// Portal construction methods. These actually create portals. // Portal construction methods. These actually create portals.
template <std::size_t... Indices> template <std::size_t... Indices>
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::Id numValues, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkmstd::index_sequence<Indices...>, vtkm::Id numValues,
vtkm::cont::DeviceAdapterId device, vtkmstd::index_sequence<Indices...>,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return CreatePortalDecorator<WritePortalType>( return CreatePortalDecorator<WritePortalType>(
numValues, numValues,
@ -476,11 +461,12 @@ struct DecoratorStorageTraits
} }
template <std::size_t... Indices> template <std::size_t... Indices>
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::Id numValues, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkmstd::index_sequence<Indices...>, vtkm::Id numValues,
vtkm::cont::DeviceAdapterId device, vtkmstd::index_sequence<Indices...>,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return CreatePortalDecorator<ReadPortalType>( return CreatePortalDecorator<ReadPortalType>(
numValues, numValues,
@ -489,11 +475,12 @@ struct DecoratorStorageTraits
} }
template <std::size_t... Indices> template <std::size_t... Indices>
VTKM_CONT static void AllocateSourceArrays(vtkm::Id numValues, VTKM_CONT static void AllocateSourceArrays(
vtkm::cont::internal::Buffer* buffers, vtkm::Id numValues,
vtkm::CopyFlag preserve, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token, vtkm::CopyFlag preserve,
vtkmstd::index_sequence<Indices...>) vtkm::cont::Token& token,
vtkmstd::index_sequence<Indices...>)
{ {
CallAllocate( CallAllocate(
IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...); IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...);
@ -519,18 +506,14 @@ public:
using ReadPortalType = typename Traits::ReadPortalType; using ReadPortalType = typename Traits::ReadPortalType;
using WritePortalType = typename Traits::WritePortalType; using WritePortalType = typename Traits::WritePortalType;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return Traits::template BufferIndex<static_cast<vtkm::IdComponent>(sizeof...(ArrayTs))>();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return Traits::GetMetaData(buffers).NumberOfValues; return Traits::GetMetaData(buffers).NumberOfValues;
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -545,17 +528,19 @@ public:
} }
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return Traits::CreateReadPortal( return Traits::CreateReadPortal(
buffers, GetNumberOfValues(buffers), IndexList{}, device, token); buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return Traits::CreateWritePortal( return Traits::CreateWritePortal(
buffers, GetNumberOfValues(buffers), IndexList{}, device, token); buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
@ -564,7 +549,13 @@ public:
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer>
CreateBuffers(const DecoratorImplT& implementation, vtkm::Id numValues, const ArrayTs&... arrays) CreateBuffers(const DecoratorImplT& implementation, vtkm::Id numValues, const ArrayTs&... arrays)
{ {
return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues), arrays...); return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues, arrays...),
arrays...);
}
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(DecoratorImplT{}, 0, ArrayTs{}...);
} }
}; };

@ -103,10 +103,15 @@ public:
// you actually try to use this read portal. // you actually try to use this read portal.
using ReadPortalType = vtkm::exec::internal::ArrayPortalDiscard<ValueType>; using ReadPortalType = vtkm::exec::internal::ArrayPortalDiscard<ValueType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
DiscardMetaData metaData;
metaData.NumberOfValues = 0;
return vtkm::cont::internal::CreateBuffers(metaData);
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag, vtkm::CopyFlag,
vtkm::cont::Token&) vtkm::cont::Token&)
{ {
@ -114,12 +119,13 @@ public:
buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues = numValues; buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues = numValues;
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues; return buffers[0].GetMetaData<DiscardMetaData>().NumberOfValues;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&, const ValueType&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -128,16 +134,17 @@ public:
// Fill is a NO-OP. // Fill is a NO-OP.
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer*, VTKM_CONT static ReadPortalType CreateReadPortal(const std::vector<vtkm::cont::internal::Buffer>&,
vtkm::cont::DeviceAdapterId, vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&) vtkm::cont::Token&)
{ {
throw vtkm::cont::ErrorBadValue("Cannot read from ArrayHandleDiscard."); throw vtkm::cont::ErrorBadValue("Cannot read from ArrayHandleDiscard.");
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token&) vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{ {
return WritePortalType(GetNumberOfValues(buffers)); return WritePortalType(GetNumberOfValues(buffers));
} }

@ -103,15 +103,16 @@ class Storage<typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::Com
using SourceStorage = vtkm::cont::internal::Storage<SourceValueType, SourceStorageTag>; using SourceStorage = vtkm::cont::internal::Storage<SourceValueType, SourceStorageTag>;
public: public:
VTKM_CONT static vtkm::IdComponent ComponentIndex(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::IdComponent ComponentIndex(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<vtkm::IdComponent>(); return buffers[0].GetMetaData<vtkm::IdComponent>();
} }
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
VTKM_CONT static Buff* SourceBuffers(Buff* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + 1; return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
} }
using ReadPortalType = using ReadPortalType =
@ -119,17 +120,13 @@ public:
using WritePortalType = using WritePortalType =
vtkm::internal::ArrayPortalExtractComponent<typename SourceStorage::WritePortalType>; vtkm::internal::ArrayPortalExtractComponent<typename SourceStorage::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return SourceStorage::GetNumberOfBuffers() + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers)); return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&, const ValueType&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -139,31 +136,33 @@ public:
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
SourceStorage::ResizeBuffers(numValues, SourceBuffers(buffers), preserve, token); SourceStorage::ResizeBuffers(numValues, SourceBuffers(buffers), preserve, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token), return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
ComponentIndex(buffers)); ComponentIndex(buffers));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token), return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
ComponentIndex(buffers)); ComponentIndex(buffers));
} }
VTKM_CONT static auto CreateBuffers(vtkm::IdComponent componentIndex, VTKM_CONT static auto CreateBuffers(vtkm::IdComponent componentIndex = 0,
const ArrayHandleType& array) const ArrayHandleType& array = ArrayHandleType{})
-> decltype(vtkm::cont::internal::CreateBuffers()) -> decltype(vtkm::cont::internal::CreateBuffers())
{ {
return vtkm::cont::internal::CreateBuffers(componentIndex, array); return vtkm::cont::internal::CreateBuffers(componentIndex, array);

@ -128,26 +128,27 @@ public:
vtkm::internal::ArrayPortalGroupVec<typename ComponentsStorage::WritePortalType, vtkm::internal::ArrayPortalGroupVec<typename ComponentsStorage::WritePortalType,
NUM_COMPONENTS>; NUM_COMPONENTS>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{ {
return ComponentsStorage::GetNumberOfBuffers(); return ComponentsStorage::CreateBuffers();
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
ComponentsStorage::ResizeBuffers(NUM_COMPONENTS * numValues, buffers, preserve, token); ComponentsStorage::ResizeBuffers(NUM_COMPONENTS * numValues, buffers, preserve, token);
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
vtkm::Id componentsSize = ComponentsStorage::GetNumberOfValues(buffers); vtkm::Id componentsSize = ComponentsStorage::GetNumberOfValues(buffers);
return componentsSize / NUM_COMPONENTS; return componentsSize / NUM_COMPONENTS;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const ValueType&, const ValueType&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -156,9 +157,10 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVec."); throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVec.");
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0) if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0)
{ {
@ -168,9 +170,10 @@ public:
return ReadPortalType(ComponentsStorage::CreateReadPortal(buffers, device, token)); return ReadPortalType(ComponentsStorage::CreateReadPortal(buffers, device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0) if ((ComponentsStorage::GetNumberOfValues(buffers) % NUM_COMPONENTS) != 0)
{ {

@ -122,20 +122,32 @@ class Storage<vtkm::VecFromPortal<ComponentsPortal>,
using ComponentsStorage = vtkm::cont::internal::Storage<ComponentType, ComponentsStorageTag>; using ComponentsStorage = vtkm::cont::internal::Storage<ComponentType, ComponentsStorageTag>;
using OffsetsStorage = vtkm::cont::internal::Storage<vtkm::Id, OffsetsStorageTag>; using OffsetsStorage = vtkm::cont::internal::Storage<vtkm::Id, OffsetsStorageTag>;
using ComponentsArray = vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>;
using OffsetsArray = vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>;
VTKM_STATIC_ASSERT_MSG( VTKM_STATIC_ASSERT_MSG(
(std::is_same<ComponentsPortal, typename ComponentsStorage::WritePortalType>::value), (std::is_same<ComponentsPortal, typename ComponentsStorage::WritePortalType>::value),
"Used invalid ComponentsPortal type with expected ComponentsStorageTag."); "Used invalid ComponentsPortal type with expected ComponentsStorageTag.");
template <typename Buff> struct Info
VTKM_CONT static Buff* ComponentsBuffers(Buff* buffers)
{ {
return buffers; std::size_t OffsetsBuffersOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ComponentsBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.OffsetsBuffersOffset);
} }
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> OffsetsBuffers(
VTKM_CONT static Buff* OffsetsBuffers(Buff* buffers) const std::vector<vtkm::cont::internal::Buffer> buffers)
{ {
return buffers + ComponentsStorage::GetNumberOfBuffers(); Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.OffsetsBuffersOffset,
buffers.end());
} }
public: public:
@ -148,17 +160,13 @@ public:
vtkm::internal::ArrayPortalGroupVecVariable<typename ComponentsStorage::WritePortalType, vtkm::internal::ArrayPortalGroupVecVariable<typename ComponentsStorage::WritePortalType,
typename OffsetsStorage::ReadPortalType>; typename OffsetsStorage::ReadPortalType>;
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return ComponentsStorage::GetNumberOfBuffers() + OffsetsStorage::GetNumberOfBuffers();
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return OffsetsStorage::GetNumberOfValues(OffsetsBuffers(buffers)) - 1; return OffsetsStorage::GetNumberOfValues(OffsetsBuffers(buffers)) - 1;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const vtkm::VecFromPortal<ComponentsPortal>&, const vtkm::VecFromPortal<ComponentsPortal>&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -167,18 +175,20 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVecVariable."); throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleGroupVecVariable.");
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType( return ReadPortalType(
ComponentsStorage::CreateReadPortal(ComponentsBuffers(buffers), device, token), ComponentsStorage::CreateReadPortal(ComponentsBuffers(buffers), device, token),
OffsetsStorage::CreateReadPortal(OffsetsBuffers(buffers), device, token)); OffsetsStorage::CreateReadPortal(OffsetsBuffers(buffers), device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType( return WritePortalType(
ComponentsStorage::CreateWritePortal(ComponentsBuffers(buffers), device, token), ComponentsStorage::CreateWritePortal(ComponentsBuffers(buffers), device, token),
@ -186,31 +196,24 @@ public:
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>& componentsArray, const ComponentsArray& componentsArray = ComponentsArray{},
const vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>& offsetsArray) const OffsetsArray& offsetsArray = OffsetsArray{})
{ {
std::vector<vtkm::cont::internal::Buffer> destBuffer( Info info;
static_cast<std::size_t>(GetNumberOfBuffers())); info.OffsetsBuffersOffset = 1 + componentsArray.GetBuffers().size();
auto destIter = destBuffer.begin(); return vtkm::cont::internal::CreateBuffers(info, componentsArray, offsetsArray);
destIter =
std::copy_n(componentsArray.GetBuffers(), ComponentsStorage::GetNumberOfBuffers(), destIter);
destIter =
std::copy_n(offsetsArray.GetBuffers(), OffsetsStorage::GetNumberOfBuffers(), destIter);
return destBuffer;
} }
VTKM_CONT static vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag> GetComponentsArray( VTKM_CONT static ComponentsArray GetComponentsArray(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<ComponentType, ComponentsStorageTag>(ComponentsBuffers(buffers)); return ComponentsArray(ComponentsBuffers(buffers));
} }
VTKM_CONT static vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag> GetOffsetsArray( VTKM_CONT static OffsetsArray GetOffsetsArray(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorageTag>(OffsetsBuffers(buffers)); return OffsetsArray(OffsetsBuffers(buffers));
} }
}; };

@ -91,34 +91,6 @@ struct VTKM_ALWAYS_EXPORT StorageTagImplicit
namespace internal namespace internal
{ {
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
VTKM_STORAGE_NO_RESIZE;
VTKM_STORAGE_NO_WRITE_PORTAL;
using ReadPortalType = ArrayPortalType;
// Implicit array has one buffer that should be empty (NumberOfBytes = 0), but holds
// the metadata for the array.
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
return buffers[0].GetMetaData<ArrayPortalType>();
}
};
/// Given an array portal, returns the buffers for the `ArrayHandle` with a storage that /// Given an array portal, returns the buffers for the `ArrayHandle` with a storage that
/// is (or is compatible with) a storage tag of `StorageTagImplicit<PortalType>`. /// is (or is compatible with) a storage tag of `StorageTagImplicit<PortalType>`.
template <typename PortalType> template <typename PortalType>
@ -141,6 +113,37 @@ VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> FunctorToArrayHandleI
vtkm::internal::ArrayPortalImplicit<FunctorType>(functor, numValues)); vtkm::internal::ArrayPortalImplicit<FunctorType>(functor, numValues));
} }
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
VTKM_STORAGE_NO_RESIZE;
VTKM_STORAGE_NO_WRITE_PORTAL;
using ReadPortalType = ArrayPortalType;
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return vtkm::cont::internal::PortalToArrayHandleImplicitBuffers(ArrayPortalType{});
}
VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
}
VTKM_CONT static ReadPortalType CreateReadPortal(
const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
return buffers[0].GetMetaData<ArrayPortalType>();
}
};
} // namespace internal } // namespace internal
namespace detail namespace detail

@ -151,7 +151,8 @@ namespace detail
struct MultiplexerGetNumberOfValuesFunctor struct MultiplexerGetNumberOfValuesFunctor
{ {
template <typename StorageType> template <typename StorageType>
VTKM_CONT vtkm::Id operator()(StorageType, const vtkm::cont::internal::Buffer* buffers) const VTKM_CONT vtkm::Id operator()(StorageType,
const std::vector<vtkm::cont::internal::Buffer>& buffers) const
{ {
return StorageType::GetNumberOfValues(buffers); return StorageType::GetNumberOfValues(buffers);
} }
@ -162,7 +163,7 @@ struct MultiplexerResizeBuffersFunctor
template <typename StorageType> template <typename StorageType>
VTKM_CONT void operator()(StorageType, VTKM_CONT void operator()(StorageType,
vtkm::Id numValues, vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) const vtkm::cont::Token& token) const
{ {
@ -174,7 +175,7 @@ struct MultiplexerFillFunctor
{ {
template <typename ValueType, typename StorageType> template <typename ValueType, typename StorageType>
VTKM_CONT void operator()(StorageType, VTKM_CONT void operator()(StorageType,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -189,7 +190,7 @@ struct MultiplexerCreateReadPortalFunctor
{ {
template <typename StorageType> template <typename StorageType>
VTKM_CONT ReadPortalType operator()(StorageType, VTKM_CONT ReadPortalType operator()(StorageType,
const vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device, vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) const vtkm::cont::Token& token) const
{ {
@ -202,7 +203,7 @@ struct MultiplexerCreateWritePortalFunctor
{ {
template <typename StorageType> template <typename StorageType>
VTKM_CONT WritePortalType operator()(StorageType, VTKM_CONT WritePortalType operator()(StorageType,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::DeviceAdapterId device, vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token) const vtkm::cont::Token& token) const
{ {
@ -217,7 +218,7 @@ struct MultiplexerArrayHandleVariantFunctor
template <typename StorageTag> template <typename StorageTag>
VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>, VTKM_CONT VariantType operator()(vtkm::cont::internal::Storage<T, StorageTag>,
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers)); return VariantType(vtkm::cont::ArrayHandle<T, StorageTag>(buffers));
} }
@ -233,15 +234,15 @@ class Storage<ValueType, StorageTagMultiplexer<StorageTags...>>
using StorageVariant = vtkm::cont::internal::Variant<StorageFor<StorageTags>...>; using StorageVariant = vtkm::cont::internal::Variant<StorageFor<StorageTags>...>;
VTKM_CONT static StorageVariant Variant(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static StorageVariant Variant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<StorageVariant>(); return buffers[0].GetMetaData<StorageVariant>();
} }
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ArrayBuffers(
VTKM_CONT static Buff* ArrayBuffers(Buff* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + 1; return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
} }
public: public:
@ -250,19 +251,15 @@ public:
using WritePortalType = using WritePortalType =
vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>; vtkm::internal::ArrayPortalMultiplexer<typename StorageFor<StorageTags>::WritePortalType...>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return std::max({ StorageFor<StorageTags>::GetNumberOfBuffers()... }) + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{}, return Variant(buffers).CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{},
ArrayBuffers(buffers)); ArrayBuffers(buffers));
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -270,7 +267,7 @@ public:
detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token); detail::MultiplexerResizeBuffersFunctor{}, numValues, ArrayBuffers(buffers), preserve, token);
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -284,9 +281,10 @@ public:
token); token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return Variant(buffers).CastAndCall( return Variant(buffers).CastAndCall(
detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{}, detail::MultiplexerCreateReadPortalFunctor<ReadPortalType>{},
@ -295,9 +293,10 @@ public:
token); token);
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return Variant(buffers).CastAndCall( return Variant(buffers).CastAndCall(
detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{}, detail::MultiplexerCreateWritePortalFunctor<WritePortalType>{},
@ -306,7 +305,7 @@ public:
token); token);
} }
VTKM_CONT static bool IsValid(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static bool IsValid(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return Variant(buffers).IsValid(); return Variant(buffers).IsValid();
} }
@ -315,21 +314,17 @@ public:
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array) VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const ArrayType& array)
{ {
VTKM_IS_ARRAY_HANDLE(ArrayType); VTKM_IS_ARRAY_HANDLE(ArrayType);
std::vector<vtkm::cont::internal::Buffer> buffers = return vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array);
vtkm::cont::internal::CreateBuffers(StorageVariant{ array.GetStorage() }, array); }
// Some arrays will require different numbers of buffers. Make sure we size the buffers VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
// array to accomodate any such one to avoid any troubles. {
std::size_t numBuffers = static_cast<std::size_t>(GetNumberOfBuffers()); return vtkm::cont::internal::CreateBuffers(StorageVariant{});
VTKM_ASSERT(numBuffers >= buffers.size());
buffers.resize(numBuffers);
return buffers;
} }
VTKM_CONT static VTKM_CONT static
typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType typename detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>::VariantType
GetArrayHandleVariant(const vtkm::cont::internal::Buffer* buffers) GetArrayHandleVariant(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return Variant(buffers).CastAndCall( return Variant(buffers).CastAndCall(
detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{}, detail::MultiplexerArrayHandleVariantFunctor<ValueType, StorageTags...>{},

@ -71,12 +71,13 @@ public:
using ReadPortalType = using ReadPortalType =
vtkm::internal::ArrayPortalOffsetsToNumComponents<typename OffsetsStorage::ReadPortalType>; vtkm::internal::ArrayPortalOffsetsToNumComponents<typename OffsetsStorage::ReadPortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{ {
return OffsetsStorage::GetNumberOfBuffers(); return OffsetsStorage::CreateBuffers();
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
vtkm::Id numOffsets = OffsetsStorage::GetNumberOfValues(buffers); vtkm::Id numOffsets = OffsetsStorage::GetNumberOfValues(buffers);
if (numOffsets < 1) if (numOffsets < 1)
@ -87,9 +88,10 @@ public:
return numOffsets - 1; return numOffsets - 1;
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
VTKM_ASSERT(OffsetsStorage::GetNumberOfValues(buffers) > 0); VTKM_ASSERT(OffsetsStorage::GetNumberOfValues(buffers) > 0);
return ReadPortalType(OffsetsStorage::CreateReadPortal(buffers, device, token)); return ReadPortalType(OffsetsStorage::CreateReadPortal(buffers, device, token));

@ -109,15 +109,27 @@ class Storage<T, vtkm::cont::StorageTagPermutation<IndexStorageTag, ValueStorage
using IndexStorage = vtkm::cont::internal::Storage<vtkm::Id, IndexStorageTag>; using IndexStorage = vtkm::cont::internal::Storage<vtkm::Id, IndexStorageTag>;
using ValueStorage = vtkm::cont::internal::Storage<T, ValueStorageTag>; using ValueStorage = vtkm::cont::internal::Storage<T, ValueStorageTag>;
template <typename Buff> using IndexArray = vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag>;
VTKM_CONT constexpr static Buff* IndexBuffers(Buff* buffers) using ValueArray = vtkm::cont::ArrayHandle<T, ValueStorageTag>;
struct Info
{ {
return buffers; std::size_t ValueBufferOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> IndexBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.ValueBufferOffset);
} }
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> ValueBuffers(
VTKM_CONT constexpr static Buff* ValueBuffers(Buff* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + IndexStorage::GetNumberOfBuffers(); Info info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.ValueBufferOffset,
buffers.end());
} }
public: public:
@ -130,17 +142,13 @@ public:
vtkm::internal::ArrayPortalPermutation<typename IndexStorage::ReadPortalType, vtkm::internal::ArrayPortalPermutation<typename IndexStorage::ReadPortalType,
typename ValueStorage::WritePortalType>; typename ValueStorage::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return (IndexStorage::GetNumberOfBuffers() + ValueStorage::GetNumberOfBuffers());
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return IndexStorage::GetNumberOfValues(IndexBuffers(buffers)); return IndexStorage::GetNumberOfValues(IndexBuffers(buffers));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const T&, const T&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -149,33 +157,44 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandlePermutation."); throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandlePermutation.");
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token), return ReadPortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token),
ValueStorage::CreateReadPortal(ValueBuffers(buffers), device, token)); ValueStorage::CreateReadPortal(ValueBuffers(buffers), device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
// Note: the index portal is always a read-only portal. // Note: the index portal is always a read-only portal.
return WritePortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token), return WritePortalType(IndexStorage::CreateReadPortal(IndexBuffers(buffers), device, token),
ValueStorage::CreateWritePortal(ValueBuffers(buffers), device, token)); ValueStorage::CreateWritePortal(ValueBuffers(buffers), device, token));
} }
VTKM_CONT static vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag> GetIndexArray( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::internal::Buffer* buffers) const IndexArray& indexArray = IndexArray{},
const ValueArray& valueArray = ValueArray{})
{ {
return vtkm::cont::ArrayHandle<vtkm::Id, IndexStorageTag>(IndexBuffers(buffers)); Info info;
info.ValueBufferOffset = 1 + indexArray.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, indexArray, valueArray);
} }
VTKM_CONT static vtkm::cont::ArrayHandle<T, ValueStorageTag> GetValueArray( VTKM_CONT static IndexArray GetIndexArray(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<T, ValueStorageTag>(ValueBuffers(buffers)); return IndexArray(IndexBuffers(buffers));
}
VTKM_CONT static ValueArray GetValueArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return ValueArray(ValueBuffers(buffers));
} }
}; };
@ -236,7 +255,7 @@ public:
VTKM_CONT VTKM_CONT
ArrayHandlePermutation(const IndexArrayHandleType& indexArray, ArrayHandlePermutation(const IndexArrayHandleType& indexArray,
const ValueArrayHandleType& valueArray) const ValueArrayHandleType& valueArray)
: Superclass(vtkm::cont::internal::CreateBuffers(indexArray, valueArray)) : Superclass(StorageType::CreateBuffers(indexArray, valueArray))
{ {
} }

@ -355,18 +355,10 @@ struct StorageTagRecombineVec
namespace detail namespace detail
{ {
// Note: Normally a decorating ArrayHandle holds the buffers of the arrays it is decorating
// in its list of arrays. However, the numbers of buffers is expected to be compile-time static
// and ArrayHandleRecombineVec needs to set the number of buffers at runtime. We cheat around
// this by stuffing the decorated buffers in the metadata. To make sure deep copies work
// right, a copy of the metadata results in a deep copy of the contained buffers. The
// vtkm::cont::internal::Buffer holding the metadata is not supposed to copy the metadata
// except for a deep copy (and when it is first set). If this behavior changes, there could
// be a performance degredation.
struct RecombineVecMetaData struct RecombineVecMetaData
{ {
mutable std::vector<vtkm::cont::internal::Buffer> PortalBuffers; mutable std::vector<vtkm::cont::internal::Buffer> PortalBuffers;
std::vector<std::vector<vtkm::cont::internal::Buffer>> ArrayBuffers; std::vector<std::size_t> ArrayBufferOffsets;
RecombineVecMetaData() = default; RecombineVecMetaData() = default;
@ -374,17 +366,7 @@ struct RecombineVecMetaData
RecombineVecMetaData& operator=(const RecombineVecMetaData& src) RecombineVecMetaData& operator=(const RecombineVecMetaData& src)
{ {
this->ArrayBuffers.resize(src.ArrayBuffers.size()); this->ArrayBufferOffsets = src.ArrayBufferOffsets;
for (std::size_t arrayIndex = 0; arrayIndex < src.ArrayBuffers.size(); ++arrayIndex)
{
this->ArrayBuffers[arrayIndex].resize(src.ArrayBuffers[arrayIndex].size());
for (std::size_t bufferIndex = 0; bufferIndex < src.ArrayBuffers[arrayIndex].size();
++bufferIndex)
{
this->ArrayBuffers[arrayIndex][bufferIndex].DeepCopyFrom(
src.ArrayBuffers[arrayIndex][bufferIndex]);
}
}
this->PortalBuffers.clear(); this->PortalBuffers.clear();
// Intentionally not copying portals. Portals will be recreated from proper array when requsted. // Intentionally not copying portals. Portals will be recreated from proper array when requsted.
@ -414,13 +396,15 @@ class Storage<vtkm::internal::RecombineVec<ReadWritePortal>,
VTKM_STATIC_ASSERT( VTKM_STATIC_ASSERT(
(std::is_same<ReadWritePortal, detail::RecombinedPortalType<ComponentType>>::value)); (std::is_same<ReadWritePortal, detail::RecombinedPortalType<ComponentType>>::value));
template <typename Buff> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> BuffersForComponent(
VTKM_CONT static Buff* BuffersForComponent(Buff* buffers, vtkm::IdComponent componentIndex) const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::IdComponent componentIndex)
{ {
return buffers[0] auto& metaData = buffers[0].GetMetaData<detail::RecombineVecMetaData>();
.template GetMetaData<detail::RecombineVecMetaData>() std::size_t index = static_cast<std::size_t>(componentIndex);
.ArrayBuffers[componentIndex] return std::vector<vtkm::cont::internal::Buffer>(
.data(); buffers.begin() + metaData.ArrayBufferOffsets[index],
buffers.begin() + metaData.ArrayBufferOffsets[index + 1]);
} }
public: public:
@ -429,20 +413,20 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>; using ReadPortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
using WritePortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>; using WritePortalType = vtkm::internal::ArrayPortalRecombineVec<ReadWritePortal>;
VTKM_CONT static vtkm::IdComponent NumberOfComponents(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::IdComponent NumberOfComponents(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return static_cast<vtkm::IdComponent>( return static_cast<vtkm::IdComponent>(
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBuffers.size()); buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBufferOffsets.size() - 1);
} }
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return SourceStorage::GetNumberOfValues(BuffersForComponent(buffers, 0)); return SourceStorage::GetNumberOfValues(BuffersForComponent(buffers, 0));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const vtkm::internal::RecombineVec<ReadWritePortal>&, const vtkm::internal::RecombineVec<ReadWritePortal>&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -451,9 +435,10 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleRecombineVec."); throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleRecombineVec.");
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::IdComponent numComponents = NumberOfComponents(buffers); vtkm::IdComponent numComponents = NumberOfComponents(buffers);
@ -488,9 +473,10 @@ public:
numComponents); numComponents);
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::IdComponent numComponents = NumberOfComponents(buffers); vtkm::IdComponent numComponents = NumberOfComponents(buffers);
@ -525,19 +511,28 @@ public:
numComponents); numComponents);
} }
VTKM_CONT static ArrayType ArrayForComponent(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ArrayType ArrayForComponent(
vtkm::IdComponent componentIndex) const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::IdComponent componentIndex)
{ {
return ArrayType(BuffersForComponent(buffers, componentIndex)); return ArrayType(BuffersForComponent(buffers, componentIndex));
} }
VTKM_CONT static void AppendComponent(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
detail::RecombineVecMetaData metaData;
metaData.ArrayBufferOffsets.push_back(1);
return vtkm::cont::internal::CreateBuffers(metaData);
}
VTKM_CONT static void AppendComponent(std::vector<vtkm::cont::internal::Buffer>& buffers,
const ArrayType& array) const ArrayType& array)
{ {
std::vector<vtkm::cont::internal::Buffer> arrayBuffers( // Add buffers of new array to our list of buffers.
array.GetBuffers(), array.GetBuffers() + SourceStorage::GetNumberOfBuffers()); buffers.insert(buffers.end(), array.GetBuffers().begin(), array.GetBuffers().end());
buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBuffers.push_back( // Update metadata for new offset to end.
std::move(arrayBuffers)); buffers[0].GetMetaData<detail::RecombineVecMetaData>().ArrayBufferOffsets.push_back(
buffers.size());
} }
}; };
@ -588,7 +583,9 @@ public:
void AppendComponentArray( void AppendComponentArray(
const vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagStride>& array) const vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagStride>& array)
{ {
StorageType::AppendComponent(this->GetBuffers(), array); std::vector<vtkm::cont::internal::Buffer> buffers = this->GetBuffers();
StorageType::AppendComponent(buffers, array);
this->SetBuffers(std::move(buffers));
} }
}; };

@ -128,25 +128,26 @@ public:
using ReadPortalType = ArrayPortalReverse<typename ArrayHandleType::ReadPortalType>; using ReadPortalType = ArrayPortalReverse<typename ArrayHandleType::ReadPortalType>;
using WritePortalType = ArrayPortalReverse<typename ArrayHandleType::WritePortalType>; using WritePortalType = ArrayPortalReverse<typename ArrayHandleType::WritePortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{ {
return SourceStorage::GetNumberOfBuffers(); return SourceStorage::CreateBuffers();
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
SourceStorage::ResizeBuffers(numValues, buffers, preserve, token); SourceStorage::ResizeBuffers(numValues, buffers, preserve, token);
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return SourceStorage::GetNumberOfValues(buffers); return SourceStorage::GetNumberOfValues(buffers);
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue, const T& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -156,16 +157,18 @@ public:
SourceStorage::Fill(buffers, fillValue, numValues - endIndex, numValues - startIndex, token); SourceStorage::Fill(buffers, fillValue, numValues - endIndex, numValues - startIndex, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(SourceStorage::CreateReadPortal(buffers, device, token)); return ReadPortalType(SourceStorage::CreateReadPortal(buffers, device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(SourceStorage::CreateWritePortal(buffers, device, token)); return WritePortalType(SourceStorage::CreateWritePortal(buffers, device, token));
} }

@ -140,10 +140,13 @@ public:
using WritePortalType = using WritePortalType =
vtkm::internal::ArrayPortalSOA<ValueType, vtkm::internal::ArrayPortalBasicWrite<ComponentType>>; vtkm::internal::ArrayPortalSOA<ValueType, vtkm::internal::ArrayPortalBasicWrite<ComponentType>>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return NUM_COMPONENTS; } VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return std::vector<vtkm::cont::internal::Buffer>(static_cast<std::size_t>(NUM_COMPONENTS));
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -155,14 +158,15 @@ public:
} }
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
// Assume all buffers are the same size. // Assume all buffers are the same size.
return static_cast<vtkm::Id>(buffers[0].GetNumberOfBytes()) / return static_cast<vtkm::Id>(buffers[0].GetNumberOfBytes()) /
static_cast<vtkm::Id>(sizeof(ComponentType)); static_cast<vtkm::Id>(sizeof(ComponentType));
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -179,9 +183,10 @@ public:
} }
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::Id numValues = GetNumberOfValues(buffers); vtkm::Id numValues = GetNumberOfValues(buffers);
ReadPortalType portal(numValues); ReadPortalType portal(numValues);
@ -197,9 +202,10 @@ public:
return portal; return portal;
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::Id numValues = GetNumberOfValues(buffers); vtkm::Id numValues = GetNumberOfValues(buffers);
WritePortalType portal(numValues); WritePortalType portal(numValues);
@ -401,7 +407,7 @@ public:
VTKM_CONT vtkm::cont::ArrayHandleBasic<ComponentType> GetArray(vtkm::IdComponent index) const VTKM_CONT vtkm::cont::ArrayHandleBasic<ComponentType> GetArray(vtkm::IdComponent index) const
{ {
return ComponentArrayType(&this->GetBuffers()[index]); return ComponentArrayType({ this->GetBuffers()[index] });
} }
VTKM_CONT void SetArray(vtkm::IdComponent index, const ComponentArrayType& array) VTKM_CONT void SetArray(vtkm::IdComponent index, const ComponentArrayType& array)

@ -163,19 +163,18 @@ public:
using ReadPortalType = vtkm::internal::ArrayPortalStrideRead<T>; using ReadPortalType = vtkm::internal::ArrayPortalStrideRead<T>;
using WritePortalType = vtkm::internal::ArrayPortalStrideWrite<T>; using WritePortalType = vtkm::internal::ArrayPortalStrideWrite<T>;
VTKM_CONT static StrideInfo& GetInfo(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static StrideInfo& GetInfo(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<StrideInfo>(); return buffers[0].GetMetaData<StrideInfo>();
} }
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() { return 2; } VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return GetInfo(buffers).NumberOfValues; return GetInfo(buffers).NumberOfValues;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer*, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>&,
const T&, const T&,
vtkm::Id, vtkm::Id,
vtkm::Id, vtkm::Id,
@ -184,32 +183,35 @@ public:
throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleStride."); throw vtkm::cont::ErrorBadType("Fill not supported for ArrayHandleStride.");
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(reinterpret_cast<const T*>(buffers[1].ReadPointerDevice(device, token)), return ReadPortalType(reinterpret_cast<const T*>(buffers[1].ReadPointerDevice(device, token)),
GetInfo(buffers)); GetInfo(buffers));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType(reinterpret_cast<T*>(buffers[1].WritePointerDevice(device, token)), return WritePortalType(reinterpret_cast<T*>(buffers[1].WritePointerDevice(device, token)),
GetInfo(buffers)); GetInfo(buffers));
} }
static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const vtkm::cont::internal::Buffer& sourceBuffer, const vtkm::cont::internal::Buffer& sourceBuffer = vtkm::cont::internal::Buffer{},
vtkm::internal::ArrayStrideInfo&& info) vtkm::internal::ArrayStrideInfo&& info = vtkm::internal::ArrayStrideInfo{})
{ {
return vtkm::cont::internal::CreateBuffers(info, sourceBuffer); return vtkm::cont::internal::CreateBuffers(info, sourceBuffer);
} }
static vtkm::cont::ArrayHandleBasic<T> GetBasicArray(const vtkm::cont::internal::Buffer* buffers) static vtkm::cont::ArrayHandleBasic<T> GetBasicArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>(buffers + 1); return vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>({ buffers[1] });
} }
}; };

@ -249,7 +249,11 @@ class Storage<typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueT
using SourceStorage = using SourceStorage =
Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>; Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>;
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 1; static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public: public:
VTKM_STORAGE_NO_RESIZE; VTKM_STORAGE_NO_RESIZE;
@ -260,54 +264,51 @@ public:
typename ArrayHandleType::ReadPortalType, typename ArrayHandleType::ReadPortalType,
typename FunctorManager::FunctorType>; typename FunctorManager::FunctorType>;
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS; return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ReadPortalType CreateReadPortal(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers,
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS); vtkm::cont::DeviceAdapterId device,
} vtkm::cont::Token& token)
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
if (device == vtkm::cont::DeviceAdapterTagUndefined{}) if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{ {
return ReadPortalType( return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token), buffers[0].GetMetaData<FunctorManager>().PrepareForControl());
buffers[0].GetMetaData<FunctorManager>().PrepareForControl());
} }
else else
{ {
return ReadPortalType( return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token), SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token)); buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token));
} }
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const ArrayHandleType& handle, const ArrayHandleType& handle = ArrayHandleType{},
const FunctorType& functor = FunctorType()) const FunctorType& functor = FunctorType())
{ {
return vtkm::cont::internal::CreateBuffers(FunctorManager(functor), handle); return vtkm::cont::internal::CreateBuffers(FunctorManager(functor), handle);
} }
VTKM_CONT static ArrayHandleType GetArray(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ArrayHandleType GetArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType, return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>(buffers + typename ArrayHandleType::StorageTag>(SourceBuffers(buffers));
NUM_METADATA_BUFFERS);
} }
VTKM_CONT static FunctorType GetFunctor(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static FunctorType GetFunctor(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<FunctorManager>().Functor; return buffers[0].GetMetaData<FunctorManager>().Functor;
} }
VTKM_CONT static NullFunctorType GetInverseFunctor(const vtkm::cont::internal::Buffer*) VTKM_CONT static NullFunctorType GetInverseFunctor(
const std::vector<vtkm::cont::internal::Buffer>&)
{ {
return NullFunctorType{}; return NullFunctorType{};
} }
@ -325,7 +326,11 @@ class Storage<
using SourceStorage = using SourceStorage =
Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>; Storage<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>;
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 2; static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 2, buffers.end());
}
public: public:
using ReadPortalType = using ReadPortalType =
@ -339,56 +344,54 @@ public:
typename FunctorManager::FunctorType, typename FunctorManager::FunctorType,
typename InverseFunctorManager::FunctorType>; typename InverseFunctorManager::FunctorType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS; return SourceStorage::GetNumberOfValues(SourceBuffers(buffers));
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS);
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
SourceStorage::ResizeBuffers(numValues, buffers + NUM_METADATA_BUFFERS, preserve, token); std::vector<vtkm::cont::internal::Buffer> sourceBuffers = SourceBuffers(buffers);
SourceStorage::ResizeBuffers(numValues, sourceBuffers, preserve, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
if (device == vtkm::cont::DeviceAdapterTagUndefined{}) if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{ {
return ReadPortalType( return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token), buffers[0].GetMetaData<FunctorManager>().PrepareForControl(),
buffers[0].GetMetaData<FunctorManager>().PrepareForControl(), buffers[1].GetMetaData<InverseFunctorManager>().PrepareForControl());
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForControl());
} }
else else
{ {
return ReadPortalType( return ReadPortalType(
SourceStorage::CreateReadPortal(buffers + NUM_METADATA_BUFFERS, device, token), SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token), buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token)); buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token));
} }
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType( return WritePortalType(
SourceStorage::CreateWritePortal(buffers + NUM_METADATA_BUFFERS, device, token), SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token), buffers[0].GetMetaData<FunctorManager>().PrepareForExecution(device, token),
buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token)); buffers[1].GetMetaData<InverseFunctorManager>().PrepareForExecution(device, token));
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const ArrayHandleType& handle, const ArrayHandleType& handle = ArrayHandleType{},
const FunctorType& functor = FunctorType(), const FunctorType& functor = FunctorType(),
const InverseFunctorType& inverseFunctor = InverseFunctorType()) const InverseFunctorType& inverseFunctor = InverseFunctorType())
{ {
@ -396,19 +399,20 @@ public:
FunctorManager(functor), InverseFunctorManager(inverseFunctor), handle); FunctorManager(functor), InverseFunctorManager(inverseFunctor), handle);
} }
VTKM_CONT static ArrayHandleType GetArray(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ArrayHandleType GetArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType, return vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>(buffers + typename ArrayHandleType::StorageTag>(SourceBuffers(buffers));
NUM_METADATA_BUFFERS);
} }
VTKM_CONT static FunctorType GetFunctor(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static FunctorType GetFunctor(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<FunctorManager>().Functor; return buffers[0].GetMetaData<FunctorManager>().Functor;
} }
VTKM_CONT static InverseFunctorType GetInverseFunctor(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static InverseFunctorType GetInverseFunctor(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[1].GetMetaData<InverseFunctorManager>().Functor; return buffers[1].GetMetaData<InverseFunctorManager>().Functor;
} }

@ -143,6 +143,12 @@ class Storage<T, StorageTagView<ST>>
using ArrayHandleType = typename detail::ViewTypeArg<T, ST>::ArrayHandle; using ArrayHandleType = typename detail::ViewTypeArg<T, ST>::ArrayHandle;
using SourceStorage = Storage<T, ST>; using SourceStorage = Storage<T, ST>;
static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
}
public: public:
VTKM_STORAGE_NO_RESIZE; VTKM_STORAGE_NO_RESIZE;
@ -150,25 +156,23 @@ public:
using WritePortalType = using WritePortalType =
vtkm::internal::ArrayPortalView<typename ArrayHandleType::WritePortalType>; vtkm::internal::ArrayPortalView<typename ArrayHandleType::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return SourceStorage::GetNumberOfBuffers() + 1;
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().NumberOfValues; return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().NumberOfValues;
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>(); vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>();
return ReadPortalType(SourceStorage::CreateReadPortal(buffers + 1, device, token), indices); return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
indices);
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const T& fillValue, const T& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -179,30 +183,36 @@ public:
vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues) vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues)
? endIndex + indices.StartIndex ? endIndex + indices.StartIndex
: indices.NumberOfValues + indices.StartIndex; : indices.NumberOfValues + indices.StartIndex;
SourceStorage::Fill(buffers + 1, fillValue, adjustedStartIndex, adjustedEndIndex, token); SourceStorage::Fill(
SourceBuffers(buffers), fillValue, adjustedStartIndex, adjustedEndIndex, token);
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>(); vtkm::internal::ViewIndices indices = buffers[0].GetMetaData<vtkm::internal::ViewIndices>();
return WritePortalType(SourceStorage::CreateWritePortal(buffers + 1, device, token), indices); return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token),
indices);
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
CreateBuffers(vtkm::Id startIndex, vtkm::Id numValues, const ArrayHandleType& array) vtkm::Id startIndex = 0,
vtkm::Id numValues = 0,
const ArrayHandleType& array = ArrayHandleType{})
{ {
return vtkm::cont::internal::CreateBuffers(vtkm::internal::ViewIndices(startIndex, numValues), return vtkm::cont::internal::CreateBuffers(vtkm::internal::ViewIndices(startIndex, numValues),
array); array);
} }
VTKM_CONT static ArrayHandleType GetSourceArray(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ArrayHandleType GetSourceArray(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return ArrayHandleType(buffers + 1); return ArrayHandleType(SourceBuffers(buffers));
} }
VTKM_CONT static vtkm::Id GetStartIndex(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetStartIndex(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().StartIndex; return buffers[0].GetMetaData<vtkm::internal::ViewIndices>().StartIndex;
} }

@ -170,60 +170,61 @@ class XGCCoordinatesStorageImpl
using SourceStorage = Storage<T, StorageTagBasic>; // only allow input AH to use StorageTagBasic using SourceStorage = Storage<T, StorageTagBasic>; // only allow input AH to use StorageTagBasic
using MetaData = XGCCoordinatesMetaData; using MetaData = XGCCoordinatesMetaData;
static MetaData& GetMetaData(const vtkm::cont::internal::Buffer* buffers) static MetaData& GetMetaData(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<MetaData>(); return buffers[0].GetMetaData<MetaData>();
} }
// Used to skip the metadata buffer and return only actual data buffers // Used to skip the metadata buffer and return only actual data buffers
template <typename Buffs> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SourceBuffers(
VTKM_CONT constexpr static Buffs* SourceBuffers(Buffs* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + 1; return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1, buffers.end());
} }
public: public:
using ReadPortalType = using ReadPortalType =
vtkm::internal::ArrayPortalXGCCoordinates<typename SourceStorage::ReadPortalType>; vtkm::internal::ArrayPortalXGCCoordinates<typename SourceStorage::ReadPortalType>;
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() VTKM_CONT static vtkm::Id GetNumberOfValues(
{ const std::vector<vtkm::cont::internal::Buffer>& buffers)
return SourceStorage::GetNumberOfBuffers() + 1; // To account for metadata
}
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return GetNumberOfValuesPerPlane(buffers) * GetNumberOfPlanesOwned(buffers); return GetNumberOfValuesPerPlane(buffers) * GetNumberOfPlanesOwned(buffers);
} }
VTKM_CONT static vtkm::Id GetNumberOfValuesPerPlane(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValuesPerPlane(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return SourceStorage::GetNumberOfValues(SourceBuffers(buffers)) / 2; return SourceStorage::GetNumberOfValues(SourceBuffers(buffers)) / 2;
} }
VTKM_CONT static vtkm::Id GetNumberOfPlanes(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfPlanes(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return GetMetaData(buffers).NumberOfPlanes; return GetMetaData(buffers).NumberOfPlanes;
} }
VTKM_CONT static vtkm::Id GetNumberOfPlanesOwned(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfPlanesOwned(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return GetMetaData(buffers).NumberOfPlanesOwned; return GetMetaData(buffers).NumberOfPlanesOwned;
} }
VTKM_CONT static vtkm::Id GetPlaneStartId(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetPlaneStartId(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return GetMetaData(buffers).PlaneStartId; return GetMetaData(buffers).PlaneStartId;
} }
VTKM_CONT static bool GetUseCylindrical(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static bool GetUseCylindrical(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return GetMetaData(buffers).UseCylindrical; return GetMetaData(buffers).UseCylindrical;
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token), return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token),
GetNumberOfPlanes(buffers), GetNumberOfPlanes(buffers),
@ -233,7 +234,7 @@ public:
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers( VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
vtkm::cont::ArrayHandle<T> array, const vtkm::cont::ArrayHandle<T>& array,
vtkm::Id numberOfPlanes, vtkm::Id numberOfPlanes,
vtkm::Id numberOfPlanesOwned, vtkm::Id numberOfPlanesOwned,
vtkm::Id planeStartId, vtkm::Id planeStartId,
@ -243,8 +244,13 @@ public:
MetaData(numberOfPlanes, numberOfPlanesOwned, planeStartId, useCylindrical), array); MetaData(numberOfPlanes, numberOfPlanesOwned, planeStartId, useCylindrical), array);
} }
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
{
return CreateBuffers(vtkm::cont::ArrayHandle<T>{}, 0, 0, 0, false);
}
VTKM_CONT static vtkm::cont::ArrayHandle<T> GetArrayHandle( VTKM_CONT static vtkm::cont::ArrayHandle<T> GetArrayHandle(
const vtkm::cont::internal::Buffer* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return vtkm::cont::ArrayHandle<T>(SourceBuffers(buffers)); return vtkm::cont::ArrayHandle<T>(SourceBuffers(buffers));
} }

@ -129,6 +129,10 @@ struct ArrayHandleZipTraits
using Tag = using Tag =
StorageTagZip<typename FirstHandleType::StorageTag, typename SecondHandleType::StorageTag>; StorageTagZip<typename FirstHandleType::StorageTag, typename SecondHandleType::StorageTag>;
/// The storage type.
///
using Storage = vtkm::cont::internal::Storage<ValueType, Tag>;
/// The superclass for ArrayHandleZip. /// The superclass for ArrayHandleZip.
/// ///
using Superclass = vtkm::cont::ArrayHandle<ValueType, Tag>; using Superclass = vtkm::cont::ArrayHandle<ValueType, Tag>;
@ -141,15 +145,27 @@ class Storage<vtkm::Pair<T1, T2>, vtkm::cont::StorageTagZip<ST1, ST2>>
using SecondStorage = Storage<T2, ST2>; using SecondStorage = Storage<T2, ST2>;
using ValueType = vtkm::Pair<T1, T2>; using ValueType = vtkm::Pair<T1, T2>;
template <typename BufferType> using FirstArrayType = vtkm::cont::ArrayHandle<T1, ST1>;
VTKM_CONT static BufferType* FirstArrayBuffers(BufferType* buffers) using SecondArrayType = vtkm::cont::ArrayHandle<T2, ST2>;
struct Info
{ {
return buffers; std::size_t SecondBuffersOffset;
};
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> FirstArrayBuffers(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{
const Info& info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + 1,
buffers.begin() + info.SecondBuffersOffset);
} }
template <typename BufferType> VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> SecondArrayBuffers(
VTKM_CONT static BufferType* SecondArrayBuffers(BufferType* buffers) const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers + FirstStorage::GetNumberOfBuffers(); const Info& info = buffers[0].GetMetaData<Info>();
return std::vector<vtkm::cont::internal::Buffer>(buffers.begin() + info.SecondBuffersOffset,
buffers.end());
} }
public: public:
@ -160,13 +176,17 @@ public:
vtkm::exec::internal::ArrayPortalZip<typename FirstStorage::WritePortalType, vtkm::exec::internal::ArrayPortalZip<typename FirstStorage::WritePortalType,
typename SecondStorage::WritePortalType>; typename SecondStorage::WritePortalType>;
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
const FirstArrayType& firstArray = FirstArrayType{},
const SecondArrayType& secondArray = SecondArrayType{})
{ {
return FirstStorage::GetNumberOfBuffers() + SecondStorage::GetNumberOfBuffers(); Info info;
info.SecondBuffersOffset = 1 + firstArray.GetBuffers().size();
return vtkm::cont::internal::CreateBuffers(info, firstArray, secondArray);
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -174,14 +194,15 @@ public:
SecondStorage::ResizeBuffers(numValues, SecondArrayBuffers(buffers), preserve, token); SecondStorage::ResizeBuffers(numValues, SecondArrayBuffers(buffers), preserve, token);
} }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
vtkm::Id numValues = FirstStorage::GetNumberOfValues(FirstArrayBuffers(buffers)); vtkm::Id numValues = FirstStorage::GetNumberOfValues(FirstArrayBuffers(buffers));
VTKM_ASSERT(numValues == SecondStorage::GetNumberOfValues(SecondArrayBuffers(buffers))); VTKM_ASSERT(numValues == SecondStorage::GetNumberOfValues(SecondArrayBuffers(buffers)));
return numValues; return numValues;
} }
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -191,29 +212,31 @@ public:
SecondStorage::Fill(SecondArrayBuffers(buffers), fillValue.second, startIndex, endIndex, token); SecondStorage::Fill(SecondArrayBuffers(buffers), fillValue.second, startIndex, endIndex, token);
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return ReadPortalType( return ReadPortalType(
FirstStorage::CreateReadPortal(FirstArrayBuffers(buffers), device, token), FirstStorage::CreateReadPortal(FirstArrayBuffers(buffers), device, token),
SecondStorage::CreateReadPortal(SecondArrayBuffers(buffers), device, token)); SecondStorage::CreateReadPortal(SecondArrayBuffers(buffers), device, token));
} }
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return WritePortalType( return WritePortalType(
FirstStorage::CreateWritePortal(FirstArrayBuffers(buffers), device, token), FirstStorage::CreateWritePortal(FirstArrayBuffers(buffers), device, token),
SecondStorage::CreateWritePortal(SecondArrayBuffers(buffers), device, token)); SecondStorage::CreateWritePortal(SecondArrayBuffers(buffers), device, token));
} }
vtkm::cont::ArrayHandle<T1, ST1> GetFirstArray(const vtkm::cont::internal::Buffer* buffers) static FirstArrayType GetFirstArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return { FirstArrayBuffers(buffers) }; return { FirstArrayBuffers(buffers) };
} }
vtkm::cont::ArrayHandle<T2, ST2> GetSecondArray(const vtkm::cont::internal::Buffer* buffers) static SecondArrayType GetSecondArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return { SecondArrayBuffers(buffers) }; return { SecondArrayBuffers(buffers) };
} }
@ -236,6 +259,9 @@ class ArrayHandleZip
// template argument is not a valid ArrayHandle type. // template argument is not a valid ArrayHandle type.
VTKM_IS_ARRAY_HANDLE(SecondHandleType); VTKM_IS_ARRAY_HANDLE(SecondHandleType);
using StorageType =
typename internal::ArrayHandleZipTraits<FirstHandleType, SecondHandleType>::Storage;
public: public:
VTKM_ARRAY_HANDLE_SUBCLASS( VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleZip, ArrayHandleZip,
@ -244,17 +270,14 @@ public:
VTKM_CONT VTKM_CONT
ArrayHandleZip(const FirstHandleType& firstArray, const SecondHandleType& secondArray) ArrayHandleZip(const FirstHandleType& firstArray, const SecondHandleType& secondArray)
: Superclass(vtkm::cont::internal::CreateBuffers(firstArray, secondArray)) : Superclass(StorageType::CreateBuffers(firstArray, secondArray))
{ {
} }
FirstHandleType GetFirstArray() const FirstHandleType GetFirstArray() const { return StorageType::GetFirstArray(this->GetBuffers()); }
{
return this->GetStorage().GetFirstArray(this->GetBuffers());
}
SecondHandleType GetSecondArray() const SecondHandleType GetSecondArray() const
{ {
return this->GetStorage().GetSecondArray(this->GetBuffers()); return StorageType::GetSecondArray(this->GetBuffers());
} }
}; };

@ -595,7 +595,8 @@ public:
VTKM_CONT VTKM_DEPRECATED(1.6, "BitField now uses a Buffer to store data.") VTKM_CONT VTKM_DEPRECATED(1.6, "BitField now uses a Buffer to store data.")
ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic> GetData() const ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic> GetData() const
{ {
return vtkm::cont::ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>(&this->Buffer); return vtkm::cont::ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>(
std::vector<vtkm::cont::internal::Buffer>(1, this->Buffer));
} }
/// Return the number of bits stored by this BitField. /// Return the number of bits stored by this BitField.

@ -118,25 +118,30 @@ public:
/// ///
using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>; using WritePortalType = vtkm::internal::ArrayPortalBasicWrite<T>;
/// \brief Returns the number of buffers required for this storage. /// \brief Create the buffers for an empty array.
/// ///
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers(); /// This is used by the `ArrayHandle` base class when constructed with no arguments.
/// A convenience subclass may construct the buffers in a different way based on
/// some provided objects.
///
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers();
/// \brief Resizes the array by changing the size of the buffers. /// \brief Resizes the array by changing the size of the buffers.
/// ///
/// Can also modify any metadata attached to the buffers. /// Can also modify any metadata attached to the buffers.
/// ///
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token); vtkm::cont::Token& token);
/// \brief Returns the number of entries allocated in the array. /// \brief Returns the number of entries allocated in the array.
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers); VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers);
/// \brief Fills the array with the given value starting and ending at the given indices. /// \brief Fills the array with the given value starting and ending at the given indices.
/// ///
VTKM_CONT static void Fill(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
const ValueType& fillValue, const ValueType& fillValue,
vtkm::Id startIndex, vtkm::Id startIndex,
vtkm::Id endIndex, vtkm::Id endIndex,
@ -144,15 +149,17 @@ public:
/// \brief Create a read-only portal on the specified device. /// \brief Create a read-only portal on the specified device.
/// ///
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token); vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token);
/// \brief Create a read/write portal on the specified device. /// \brief Create a read/write portal on the specified device.
/// ///
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
}; };
#endif // VTKM_DOXYGEN_ONLY #endif // VTKM_DOXYGEN_ONLY
@ -175,22 +182,24 @@ struct StorageTraits<vtkm::cont::internal::Storage<T, S>>
using Tag = S; using Tag = S;
}; };
#define VTKM_STORAGE_NO_RESIZE \ #define VTKM_STORAGE_NO_RESIZE \
VTKM_CONT static void ResizeBuffers( \ VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, \
vtkm::Id numValues, vtkm::cont::internal::Buffer* buffers, vtkm::CopyFlag, vtkm::cont::Token&) \ const std::vector<vtkm::cont::internal::Buffer>& buffers, \
{ \ vtkm::CopyFlag, \
vtkm::cont::internal::detail::StorageNoResizeImpl( \ vtkm::cont::Token&) \
GetNumberOfValues(buffers), \ { \
numValues, \ vtkm::cont::internal::detail::StorageNoResizeImpl( \
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \ GetNumberOfValues(buffers), \
} \ numValues, \
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
} \
using ResizeBuffersEatComma = void using ResizeBuffersEatComma = void
#define VTKM_STORAGE_NO_WRITE_PORTAL \ #define VTKM_STORAGE_NO_WRITE_PORTAL \
using WritePortalType = vtkm::internal::ArrayPortalDummy< \ using WritePortalType = vtkm::internal::ArrayPortalDummy< \
typename vtkm::cont::internal::StorageTraits<Storage>::ValueType>; \ typename vtkm::cont::internal::StorageTraits<Storage>::ValueType>; \
VTKM_CONT static void Fill( \ VTKM_CONT static void Fill( \
vtkm::cont::internal::Buffer*, \ const std::vector<vtkm::cont::internal::Buffer>&, \
const typename vtkm::cont::internal::StorageTraits<Storage>::ValueType&, \ const typename vtkm::cont::internal::StorageTraits<Storage>::ValueType&, \
vtkm::Id, \ vtkm::Id, \
vtkm::Id, \ vtkm::Id, \
@ -201,7 +210,9 @@ struct StorageTraits<vtkm::cont::internal::Storage<T, S>>
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \ vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
} \ } \
VTKM_CONT static WritePortalType CreateWritePortal( \ VTKM_CONT static WritePortalType CreateWritePortal( \
vtkm::cont::internal::Buffer*, vtkm::cont::DeviceAdapterId, vtkm::cont::Token&) \ const std::vector<vtkm::cont::internal::Buffer>&, \
vtkm::cont::DeviceAdapterId, \
vtkm::cont::Token&) \
{ \ { \
throw vtkm::cont::ErrorBadAllocation( \ throw vtkm::cont::ErrorBadAllocation( \
"Cannot write to arrays with storage type of " + \ "Cannot write to arrays with storage type of " + \

@ -136,8 +136,7 @@ UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::Cop
using AH = vtkm::cont::ArrayHandle<T, S>; using AH = vtkm::cont::ArrayHandle<T, S>;
AH* arrayHandle = reinterpret_cast<AH*>(mem); AH* arrayHandle = reinterpret_cast<AH*>(mem);
auto componentArray = vtkm::cont::ArrayExtractComponent(*arrayHandle, componentIndex, allowCopy); auto componentArray = vtkm::cont::ArrayExtractComponent(*arrayHandle, componentIndex, allowCopy);
vtkm::cont::internal::Buffer* buffers = componentArray.GetBuffers(); return componentArray.GetBuffers();
return std::vector<vtkm::cont::internal::Buffer>(buffers, buffers + 2);
} }
template <typename T, typename S> template <typename T, typename S>

@ -72,10 +72,10 @@ public:
"Storage implementation declare VTKM_STORAGE_OLD_STYLE at the bottom " "Storage implementation declare VTKM_STORAGE_OLD_STYLE at the bottom "
"of its implementation."); "of its implementation.");
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT vtkm::cont::internal::Buffer* GetBuffers() const VTKM_CONT std::vector<vtkm::cont::internal::Buffer> GetBuffers() const
{ {
this->BufferAsStorageWrapper.SetMetaData(*this); this->BufferAsStorageWrapper.SetMetaData(*this);
return &this->BufferAsStorageWrapper; return std::vector<vtkm::cont::internal::Buffer>(1, this->BufferAsStorageWrapper);
} }
VTKM_CONT ArrayHandleDeprecated(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT ArrayHandleDeprecated(const vtkm::cont::internal::Buffer* buffers)

@ -775,7 +775,7 @@ vtkm::BufferSizeType Buffer::GetNumberOfBytes() const
void Buffer::SetNumberOfBytes(vtkm::BufferSizeType numberOfBytes, void Buffer::SetNumberOfBytes(vtkm::BufferSizeType numberOfBytes,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token) const
{ {
LockType lock = this->Internals->GetLock(); LockType lock = this->Internals->GetLock();
detail::BufferHelper::SetNumberOfBytes(this->Internals, lock, numberOfBytes, preserve, token); detail::BufferHelper::SetNumberOfBytes(this->Internals, lock, numberOfBytes, preserve, token);
@ -1050,7 +1050,7 @@ vtkm::cont::internal::BufferInfo Buffer::GetHostBufferInfo() const
return this->Internals->GetHostBuffer(lock); return this->Internals->GetHostBuffer(lock);
} }
vtkm::cont::internal::TransferredBuffer Buffer::TakeHostBufferOwnership() vtkm::cont::internal::TransferredBuffer Buffer::TakeHostBufferOwnership() const
{ {
// A Token should not be declared within the scope of a lock. when the token goes out of scope // A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to acquire the lock, which is undefined behavior of the thread already has // it will attempt to acquire the lock, which is undefined behavior of the thread already has
@ -1067,7 +1067,7 @@ vtkm::cont::internal::TransferredBuffer Buffer::TakeHostBufferOwnership()
} }
vtkm::cont::internal::TransferredBuffer Buffer::TakeDeviceBufferOwnership( vtkm::cont::internal::TransferredBuffer Buffer::TakeDeviceBufferOwnership(
vtkm::cont::DeviceAdapterId device) vtkm::cont::DeviceAdapterId device) const
{ {
if (device.IsValueValid()) if (device.IsValueValid())
{ {

@ -123,7 +123,7 @@ public:
/// ///
VTKM_CONT void SetNumberOfBytes(vtkm::BufferSizeType numberOfBytes, VTKM_CONT void SetNumberOfBytes(vtkm::BufferSizeType numberOfBytes,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token); vtkm::cont::Token& token) const;
private: private:
VTKM_CONT bool MetaDataIsType(const std::string& type) const; VTKM_CONT bool MetaDataIsType(const std::string& type) const;
@ -302,13 +302,13 @@ public:
/// \brief Transfer ownership of the Host `BufferInfo` from this buffer /// \brief Transfer ownership of the Host `BufferInfo` from this buffer
/// to the caller. This is used to allow memory owned by VTK-m to be /// to the caller. This is used to allow memory owned by VTK-m to be
/// transferred to an owner whose lifespan is longer /// transferred to an owner whose lifespan is longer
VTKM_CONT vtkm::cont::internal::TransferredBuffer TakeHostBufferOwnership(); VTKM_CONT vtkm::cont::internal::TransferredBuffer TakeHostBufferOwnership() const;
/// \brief Transfer ownership of the device `BufferInfo` from this buffer /// \brief Transfer ownership of the device `BufferInfo` from this buffer
/// to the caller. This is used to allow memory owned by VTK-m to be /// to the caller. This is used to allow memory owned by VTK-m to be
/// transferred to an owner whose lifespan is longer /// transferred to an owner whose lifespan is longer
VTKM_CONT vtkm::cont::internal::TransferredBuffer TakeDeviceBufferOwnership( VTKM_CONT vtkm::cont::internal::TransferredBuffer TakeDeviceBufferOwnership(
vtkm::cont::DeviceAdapterId device); vtkm::cont::DeviceAdapterId device) const;
/// \brief Fill up the buffer with particular values. /// \brief Fill up the buffer with particular values.
/// ///

@ -100,21 +100,20 @@ class StorageDeprecated
using ArrayType = vtkm::cont::internal::ArrayHandleDeprecated<T, StorageTag>; using ArrayType = vtkm::cont::internal::ArrayHandleDeprecated<T, StorageTag>;
VTKM_CONT static ArrayType GetArray(const vtkm::cont::internal::Buffer* buffers) VTKM_CONT static ArrayType GetArray(const std::vector<vtkm::cont::internal::Buffer>& buffers)
{ {
return buffers[0].GetMetaData<ArrayType>(); return buffers[0].GetMetaData<ArrayType>();
} }
public: public:
VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers() { return 1; } VTKM_CONT static vtkm::Id GetNumberOfValues(
const std::vector<vtkm::cont::internal::Buffer>& buffers)
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{ {
return GetArray(buffers).GetNumberOfValues(); return GetArray(buffers).GetNumberOfValues();
} }
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::CopyFlag preserve, vtkm::CopyFlag preserve,
vtkm::cont::Token& token) vtkm::cont::Token& token)
{ {
@ -129,9 +128,10 @@ public:
} }
} }
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers, VTKM_CONT static ReadPortalType CreateReadPortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
if (device == vtkm::cont::DeviceAdapterTagUndefined{}) if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{ {
@ -153,10 +153,11 @@ public:
} }
private: private:
VTKM_CONT static WritePortalType CreateWritePortalImpl(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortalImpl(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token, vtkm::cont::DeviceAdapterId device,
std::true_type) vtkm::cont::Token& token,
std::true_type)
{ {
if (device == vtkm::cont::DeviceAdapterTagUndefined{}) if (device == vtkm::cont::DeviceAdapterTagUndefined{})
{ {
@ -177,10 +178,11 @@ private:
} }
} }
VTKM_CONT static WritePortalType CreateWritePortalImpl(vtkm::cont::internal::Buffer*, VTKM_CONT static WritePortalType CreateWritePortalImpl(
vtkm::cont::DeviceAdapterId, const std::vector<vtkm::cont::internal::Buffer>&,
vtkm::cont::Token&, vtkm::cont::DeviceAdapterId,
std::false_type) vtkm::cont::Token&,
std::false_type)
{ {
throw vtkm::cont::ErrorBadType("Attempted to get a writable portal to a read-only array."); throw vtkm::cont::ErrorBadType("Attempted to get a writable portal to a read-only array.");
} }
@ -188,32 +190,33 @@ private:
using SupportsWrite = vtkm::internal::PortalSupportsSets<WritePortalType>; using SupportsWrite = vtkm::internal::PortalSupportsSets<WritePortalType>;
public: public:
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers, VTKM_CONT static WritePortalType CreateWritePortal(
vtkm::cont::DeviceAdapterId device, const std::vector<vtkm::cont::internal::Buffer>& buffers,
vtkm::cont::Token& token) vtkm::cont::DeviceAdapterId device,
vtkm::cont::Token& token)
{ {
return CreateWritePortalImpl(buffers, device, token, SupportsWrite{}); return CreateWritePortalImpl(buffers, device, token, SupportsWrite{});
} }
}; };
#define VTKM_STORAGE_OLD_STYLE \ #define VTKM_STORAGE_OLD_STYLE \
public: \ public: \
using HasOldBridge = std::true_type; \ using HasOldBridge = std::true_type; \
using ReadPortalType = PortalConstType; \ using ReadPortalType = PortalConstType; \
using WritePortalType = PortalType; \ using WritePortalType = PortalType; \
\ \
private: \ private: \
using StorageDeprecated = \ using StorageDeprecated = \
vtkm::cont::internal::StorageDeprecated<Storage, ReadPortalType, WritePortalType>; \ vtkm::cont::internal::StorageDeprecated<Storage, ReadPortalType, WritePortalType>; \
\ \
public: \ public: \
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers) \ VTKM_CONT static vtkm::Id GetNumberOfValues( \
{ \ const std::vector<vtkm::cont::internal::Buffer>& buffers) \
return StorageDeprecated::GetNumberOfValues(buffers); \ { \
} \ return StorageDeprecated::GetNumberOfValues(buffers); \
static constexpr auto& GetNumberOfBuffers = StorageDeprecated::GetNumberOfBuffers; \ } \
static constexpr auto& ResizeBuffers = StorageDeprecated::ResizeBuffers; \ static constexpr auto& ResizeBuffers = StorageDeprecated::ResizeBuffers; \
static constexpr auto& CreateReadPortal = StorageDeprecated::CreateReadPortal; \ static constexpr auto& CreateReadPortal = StorageDeprecated::CreateReadPortal; \
static constexpr auto& CreateWritePortal = StorageDeprecated::CreateWritePortal static constexpr auto& CreateWritePortal = StorageDeprecated::CreateWritePortal
} }

@ -601,7 +601,7 @@ private:
Algorithm::Schedule(functor, ARRAY_SIZE * 2); Algorithm::Schedule(functor, ARRAY_SIZE * 2);
} }
transferredMemory = copyOfHandle.GetBuffers()->TakeHostBufferOwnership(); transferredMemory = copyOfHandle.GetBuffers()[0].TakeHostBufferOwnership();
VTKM_TEST_ASSERT(copyOfHandle.GetNumberOfValues() == ARRAY_SIZE * 2, VTKM_TEST_ASSERT(copyOfHandle.GetNumberOfValues() == ARRAY_SIZE * 2,
"Array not allocated correctly."); "Array not allocated correctly.");