Merge topic 'arrayhandleimplicit-use-buffer'

f66dc780c Update ArrayHandleImplicit to new array style with Buffer

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !2246
This commit is contained in:
Kenneth Moreland 2020-10-22 14:15:43 +00:00 committed by Kitware Robot
commit 447bae88d0
14 changed files with 293 additions and 498 deletions

@ -47,20 +47,13 @@ using StorageTagConstantSuperclass =
template <typename T>
struct Storage<T, vtkm::cont::StorageTagConstant> : Storage<T, StorageTagConstantSuperclass<T>>
{
using Superclass = Storage<T, StorageTagConstantSuperclass<T>>;
using Superclass::Superclass;
};
template <typename T, typename Device>
struct ArrayTransfer<T, vtkm::cont::StorageTagConstant, Device>
: ArrayTransfer<T, StorageTagConstantSuperclass<T>, Device>
{
using Superclass = ArrayTransfer<T, StorageTagConstantSuperclass<T>, Device>;
using Superclass::Superclass;
};
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagConstant);
/// \brief An array handle with a constant value.
///
/// ArrayHandleConstant is an implicit array handle with a constant value. A
@ -79,9 +72,8 @@ public:
VTKM_CONT
ArrayHandleConstant(T value, vtkm::Id numberOfValues = 0)
: Superclass(typename internal::Storage<T, StorageTag>::PortalConstType(
internal::ConstantFunctor<T>(value),
numberOfValues))
: Superclass(internal::FunctorToArrayHandleImplicitBuffers(internal::ConstantFunctor<T>(value),
numberOfValues))
{
}
};

@ -10,8 +10,7 @@
#ifndef vtk_m_cont_ArrayHandleCounting_h
#define vtk_m_cont_ArrayHandleCounting_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageImplicit.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/VecTraits.h>
@ -52,24 +51,6 @@ public:
{
}
template <typename OtherValueType>
VTKM_EXEC_CONT ArrayPortalCounting(const ArrayPortalCounting<OtherValueType>& src)
: Start(src.Start)
, Step(src.Step)
, NumberOfValues(src.NumberOfValues)
{
}
template <typename OtherValueType>
VTKM_EXEC_CONT ArrayPortalCounting<ValueType>& operator=(
const ArrayPortalCounting<OtherValueType>& src)
{
this->Start = src.Start;
this->Step = src.Step;
this->NumberOfValues = src.NumberOfValues;
return *this;
}
VTKM_EXEC_CONT
ValueType GetStart() const { return this->Start; }
@ -98,20 +79,13 @@ using StorageTagCountingSuperclass =
template <typename T>
struct Storage<T, vtkm::cont::StorageTagCounting> : Storage<T, StorageTagCountingSuperclass<T>>
{
using Superclass = Storage<T, StorageTagCountingSuperclass<T>>;
using Superclass::Superclass;
};
template <typename T, typename Device>
struct ArrayTransfer<T, vtkm::cont::StorageTagCounting, Device>
: ArrayTransfer<T, StorageTagCountingSuperclass<T>, Device>
{
using Superclass = ArrayTransfer<T, StorageTagCountingSuperclass<T>, Device>;
using Superclass::Superclass;
};
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagCounting);
/// ArrayHandleCounting is a specialization of ArrayHandle. By default it
/// contains a increment value, that is increment for each step between zero
/// and the passed in length
@ -126,7 +100,8 @@ public:
VTKM_CONT
ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm::Id length)
: Superclass(internal::ArrayPortalCounting<CountingValueType>(start, step, length))
: Superclass(internal::PortalToArrayHandleImplicitBuffers(
internal::ArrayPortalCounting<CountingValueType>(start, step, length)))
{
}
};

@ -0,0 +1,75 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/ArrayHandleImplicit.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
BufferMetaDataImplicit::BufferMetaDataImplicit(const BufferMetaDataImplicit& src)
: Deleter(src.Deleter)
, Copier(src.Copier)
{
if (src.Portal)
{
VTKM_ASSERT(src.Deleter);
VTKM_ASSERT(src.Copier);
this->Portal = src.Copier(src.Portal);
}
else
{
this->Portal = nullptr;
}
}
BufferMetaDataImplicit::~BufferMetaDataImplicit()
{
if (this->Portal)
{
VTKM_ASSERT(this->Deleter);
this->Deleter(this->Portal);
this->Portal = nullptr;
}
}
std::unique_ptr<vtkm::cont::internal::BufferMetaData> BufferMetaDataImplicit::DeepCopy() const
{
return std::unique_ptr<vtkm::cont::internal::BufferMetaData>(new BufferMetaDataImplicit(*this));
}
namespace detail
{
vtkm::cont::internal::BufferMetaDataImplicit* GetImplicitMetaData(
const vtkm::cont::internal::Buffer& buffer)
{
vtkm::cont::internal::BufferMetaDataImplicit* metadata =
dynamic_cast<vtkm::cont::internal::BufferMetaDataImplicit*>(buffer.GetMetaData());
VTKM_ASSERT(metadata && "Buffer for implicit array does not have correct metadata.");
return metadata;
}
} // namespace detail
}
}
} // namespace vtkm::cont::internal
namespace vtkm
{
namespace cont
{
}
} // namespace vtkm::cont::detail

@ -11,30 +11,15 @@
#define vtk_m_cont_ArrayHandleImplicit_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageImplicit.h>
#include <vtkmstd/is_trivial.h>
namespace vtkm
{
namespace cont
{
namespace detail
namespace internal
{
template <class FunctorType_>
class VTKM_ALWAYS_EXPORT ArrayPortalImplicit;
/// A convenience class that provides a typedef to the appropriate tag for
/// a implicit array container.
template <typename FunctorType>
struct ArrayHandleImplicitTraits
{
using ValueType = decltype(FunctorType{}(vtkm::Id{}));
using StorageTag = vtkm::cont::StorageTagImplicit<ArrayPortalImplicit<FunctorType>>;
using Superclass = vtkm::cont::ArrayHandle<ValueType, StorageTag>;
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
};
/// \brief An array portal that returns the result of a functor
///
/// This array portal is similar to an implicit array i.e an array that is
@ -48,8 +33,8 @@ template <class FunctorType_>
class VTKM_ALWAYS_EXPORT ArrayPortalImplicit
{
public:
using ValueType = typename ArrayHandleImplicitTraits<FunctorType_>::ValueType;
using FunctorType = FunctorType_;
using ValueType = decltype(FunctorType{}(vtkm::Id{}));
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
@ -82,8 +67,170 @@ private:
vtkm::Id NumberOfValues;
};
} // namespace internal
namespace cont
{
/// \brief An implementation for read-only implicit arrays.
///
/// It is sometimes the case that you want VTK-m to operate on an array of
/// implicit values. That is, rather than store the data in an actual array, it
/// is gerenated on the fly by a function. This is handled in VTK-m by creating
/// an ArrayHandle in VTK-m with a StorageTagImplicit type of \c Storage. This
/// tag itself is templated to specify an ArrayPortal that generates the
/// desired values. An ArrayHandle created with this tag will raise an error on
/// any operation that tries to modify it.
///
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT StorageTagImplicit
{
using PortalType = ArrayPortalType;
};
namespace internal
{
struct VTKM_CONT_EXPORT BufferMetaDataImplicit : vtkm::cont::internal::BufferMetaData
{
void* Portal;
using DeleterType = void(void*);
DeleterType* Deleter;
using CopierType = void*(void*);
CopierType* Copier;
template <typename PortalType>
BufferMetaDataImplicit(const PortalType& portal)
: Portal(new PortalType(portal))
, Deleter([](void* p) { delete reinterpret_cast<PortalType*>(p); })
, Copier([](void* p) -> void* { return new PortalType(*reinterpret_cast<PortalType*>(p)); })
{
}
VTKM_CONT BufferMetaDataImplicit(const BufferMetaDataImplicit& src);
BufferMetaDataImplicit& operator=(const BufferMetaDataImplicit&) = delete;
VTKM_CONT ~BufferMetaDataImplicit() override;
VTKM_CONT std::unique_ptr<vtkm::cont::internal::BufferMetaData> DeepCopy() const override;
};
namespace detail
{
VTKM_CONT_EXPORT vtkm::cont::internal::BufferMetaDataImplicit* GetImplicitMetaData(
const vtkm::cont::internal::Buffer& buffer);
} // namespace detail
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
using ReadPortalType = ArrayPortalType;
// Note that this portal is almost certainly read-only, so you will probably get
// an error if you try to write to it.
using WritePortalType = ArrayPortalType;
// Implicit array has one buffer that should be empty (NumberOfBytes = 0), but holds
// the metadata for the array.
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
{
vtkm::cont::internal::BufferMetaDataImplicit* metadata =
detail::GetImplicitMetaData(buffers[0]);
VTKM_ASSERT(metadata->Portal);
return reinterpret_cast<ArrayPortalType*>(metadata->Portal)->GetNumberOfValues();
}
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
vtkm::cont::internal::Buffer* buffers,
vtkm::CopyFlag,
vtkm::cont::Token&)
{
if (numValues == GetNumberOfValues(buffers))
{
// In general, we don't allow resizing of the array, but if it was "allocated" to the
// correct size, we will allow that.
}
else
{
throw vtkm::cont::ErrorBadAllocation("Cannot allocate/resize implicit arrays.");
}
}
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
vtkm::cont::internal::BufferMetaDataImplicit* metadata =
detail::GetImplicitMetaData(buffers[0]);
VTKM_ASSERT(metadata->Portal);
return *reinterpret_cast<ReadPortalType*>(metadata->Portal);
}
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer*,
vtkm::cont::DeviceAdapterId,
vtkm::cont::Token&)
{
throw vtkm::cont::ErrorBadAllocation("Cannot write to implicit arrays.");
}
};
/// 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>`.
template <typename PortalType>
VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> PortalToArrayHandleImplicitBuffers(
const PortalType& portal)
{
std::vector<vtkm::cont::internal::Buffer> buffers(1);
buffers[0].SetMetaData(std::unique_ptr<vtkm::cont::internal::BufferMetaData>(
new vtkm::cont::internal::BufferMetaDataImplicit(portal)));
return buffers;
}
/// Given a functor and the number of values, returns the buffers for the `ArrayHandleImplicit`
/// for the given functor.
template <typename FunctorType>
VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> FunctorToArrayHandleImplicitBuffers(
const FunctorType& functor,
vtkm::Id numValues)
{
return PortalToArrayHandleImplicitBuffers(
vtkm::internal::ArrayPortalImplicit<FunctorType>(functor, numValues));
}
} // namespace internal
namespace detail
{
/// A convenience class that provides a typedef to the appropriate tag for
/// a implicit array container.
template <typename FunctorType>
struct ArrayHandleImplicitTraits
{
using ValueType = decltype(FunctorType{}(vtkm::Id{}));
using PortalType = vtkm::internal::ArrayPortalImplicit<FunctorType>;
using StorageTag = vtkm::cont::StorageTagImplicit<PortalType>;
using Superclass = vtkm::cont::ArrayHandle<ValueType, StorageTag>;
using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
};
} // namespace detail
// This can go away once ArrayHandle is replaced with ArrayHandleNewStyle
template <typename PortalType>
VTKM_ARRAY_HANDLE_NEW_STYLE(typename PortalType::ValueType,
vtkm::cont::StorageTagImplicit<PortalType>);
/// \brief An \c ArrayHandle that computes values on the fly.
///
/// \c ArrayHandleImplicit is a specialization of ArrayHandle.
@ -97,6 +244,7 @@ class VTKM_ALWAYS_EXPORT ArrayHandleImplicit
{
private:
using ArrayTraits = typename detail::ArrayHandleImplicitTraits<FunctorType>;
using PortalType = typename ArrayTraits::PortalType;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleImplicit,
@ -105,7 +253,7 @@ public:
VTKM_CONT
ArrayHandleImplicit(FunctorType functor, vtkm::Id length)
: Superclass(typename ArrayTraits::StorageType::PortalType(functor, length))
: Superclass(internal::PortalToArrayHandleImplicitBuffers(PortalType(functor, length)))
{
}
};
@ -144,7 +292,7 @@ struct SerializableTypeString<vtkm::cont::ArrayHandleImplicit<Functor>>
template <typename Functor>
struct SerializableTypeString<vtkm::cont::ArrayHandle<
typename vtkm::cont::detail::ArrayHandleImplicitTraits<Functor>::ValueType,
vtkm::cont::StorageTagImplicit<vtkm::cont::detail::ArrayPortalImplicit<Functor>>>>
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalImplicit<Functor>>>>
: SerializableTypeString<vtkm::cont::ArrayHandleImplicit<Functor>>
{
};
@ -183,7 +331,7 @@ public:
template <typename Functor>
struct Serialization<vtkm::cont::ArrayHandle<
typename vtkm::cont::detail::ArrayHandleImplicitTraits<Functor>::ValueType,
vtkm::cont::StorageTagImplicit<vtkm::cont::detail::ArrayPortalImplicit<Functor>>>>
vtkm::cont::StorageTagImplicit<vtkm::internal::ArrayPortalImplicit<Functor>>>>
: Serialization<vtkm::cont::ArrayHandleImplicit<Functor>>
{
};

@ -14,6 +14,17 @@
namespace vtkm
{
namespace internal
{
struct VTKM_ALWAYS_EXPORT IndexFunctor
{
VTKM_EXEC_CONT vtkm::Id operator()(vtkm::Id index) const { return index; }
};
} // namespace internal
namespace cont
{
@ -24,32 +35,19 @@ struct VTKM_ALWAYS_EXPORT StorageTagIndex
namespace internal
{
struct VTKM_ALWAYS_EXPORT IndexFunctor
{
VTKM_EXEC_CONT
vtkm::Id operator()(vtkm::Id index) const { return index; }
};
using StorageTagIndexSuperclass =
typename vtkm::cont::ArrayHandleImplicit<IndexFunctor>::StorageTag;
typename vtkm::cont::ArrayHandleImplicit<vtkm::internal::IndexFunctor>::StorageTag;
template <>
struct Storage<vtkm::Id, vtkm::cont::StorageTagIndex> : Storage<vtkm::Id, StorageTagIndexSuperclass>
{
using Superclass = Storage<vtkm::Id, StorageTagIndexSuperclass>;
using Superclass::Superclass;
};
template <typename Device>
struct ArrayTransfer<vtkm::Id, vtkm::cont::StorageTagIndex, Device>
: ArrayTransfer<vtkm::Id, StorageTagIndexSuperclass, Device>
{
using Superclass = ArrayTransfer<vtkm::Id, StorageTagIndexSuperclass, Device>;
using Superclass::Superclass;
};
} // namespace internal
template <>
VTKM_ARRAY_HANDLE_NEW_STYLE(vtkm::Id, vtkm::cont::StorageTagIndex);
/// \brief An implicit array handle containing the its own indices.
///
/// \c ArrayHandleIndex is an implicit array handle containing the values
@ -65,8 +63,7 @@ public:
VTKM_CONT
ArrayHandleIndex(vtkm::Id length)
: Superclass(
typename internal::Storage<vtkm::Id, StorageTagIndex>::PortalType(internal::IndexFunctor{},
length))
internal::FunctorToArrayHandleImplicitBuffers(vtkm::internal::IndexFunctor{}, length))
{
}
};

@ -10,8 +10,7 @@
#ifndef vtk_m_cont_ArrayHandleUniformPointCoordinates_h
#define vtk_m_cont_ArrayHandleUniformPointCoordinates_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageImplicit.h>
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/internal/ArrayPortalUniformPointCoordinates.h>
namespace vtkm
@ -33,22 +32,13 @@ template <>
struct Storage<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>
: Storage<vtkm::Vec3f, StorageTagUniformPointsSuperclass>
{
using Superclass = Storage<vtkm::Vec3f, StorageTagUniformPointsSuperclass>;
using Superclass::Superclass;
};
template <typename Device>
struct ArrayTransfer<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints, Device>
: ArrayTransfer<vtkm::Vec3f, StorageTagUniformPointsSuperclass, Device>
{
using Superclass = ArrayTransfer<vtkm::Vec3f, StorageTagUniformPointsSuperclass, Device>;
using Superclass::Superclass;
};
} // namespace internal
template <>
VTKM_ARRAY_HANDLE_NEW_STYLE(vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints);
/// ArrayHandleUniformPointCoordinates is a specialization of ArrayHandle. It
/// contains the information necessary to compute the point coordinates in a
/// uniform orthogonal grid (extent, origin, and spacing) and implicitly
@ -70,7 +60,7 @@ public:
ArrayHandleUniformPointCoordinates(vtkm::Id3 dimensions,
ValueType origin = ValueType(0.0f, 0.0f, 0.0f),
ValueType spacing = ValueType(1.0f, 1.0f, 1.0f))
: Superclass(StorageType(
: Superclass(internal::PortalToArrayHandleImplicitBuffers(
vtkm::internal::ArrayPortalUniformPointCoordinates(dimensions, origin, spacing)))
{
}

@ -41,7 +41,7 @@ namespace cont
namespace detail
{
vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
vtkm::cont::internal::BufferMetaDataBitField* GetBitFieldMetaData(
const vtkm::cont::internal::Buffer& buffer)
{
vtkm::cont::internal::BufferMetaData* generalMetaData = buffer.GetMetaData();
@ -49,22 +49,22 @@ vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
{
VTKM_LOG_F(vtkm::cont::LogLevel::Warn, "BitField has buffer with no metadata. Setting.");
const_cast<vtkm::cont::internal::Buffer&>(buffer).SetMetaData(
vtkm::cont::internal::BitFieldMetaData{});
vtkm::cont::internal::BufferMetaDataBitField{});
generalMetaData = buffer.GetMetaData();
VTKM_ASSERT(generalMetaData != nullptr);
}
vtkm::cont::internal::BitFieldMetaData* metadata =
dynamic_cast<vtkm::cont::internal::BitFieldMetaData*>(generalMetaData);
vtkm::cont::internal::BufferMetaDataBitField* metadata =
dynamic_cast<vtkm::cont::internal::BufferMetaDataBitField*>(generalMetaData);
if (metadata == nullptr)
{
VTKM_LOG_F(vtkm::cont::LogLevel::Error,
"BitField has a buffer with metadata of the wrong type. "
"Replacing, but this will likely cause problems.");
const_cast<vtkm::cont::internal::Buffer&>(buffer).SetMetaData(
vtkm::cont::internal::BitFieldMetaData{});
vtkm::cont::internal::BufferMetaDataBitField{});
generalMetaData = buffer.GetMetaData();
metadata = dynamic_cast<vtkm::cont::internal::BitFieldMetaData*>(generalMetaData);
metadata = dynamic_cast<vtkm::cont::internal::BufferMetaDataBitField*>(generalMetaData);
VTKM_ASSERT(metadata != nullptr);
}
@ -79,18 +79,18 @@ vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
namespace internal
{
BitFieldMetaData::~BitFieldMetaData() {}
BufferMetaDataBitField::~BufferMetaDataBitField() {}
std::unique_ptr<vtkm::cont::internal::BufferMetaData> BitFieldMetaData::DeepCopy() const
std::unique_ptr<vtkm::cont::internal::BufferMetaData> BufferMetaDataBitField::DeepCopy() const
{
return std::unique_ptr<vtkm::cont::internal::BufferMetaData>(new BitFieldMetaData(*this));
return std::unique_ptr<vtkm::cont::internal::BufferMetaData>(new BufferMetaDataBitField(*this));
}
} // namespace internal
BitField::BitField()
{
this->Buffer.SetMetaData(internal::BitFieldMetaData{});
this->Buffer.SetMetaData(internal::BufferMetaDataBitField{});
}
vtkm::Id BitField::GetNumberOfBits() const

@ -36,11 +36,11 @@ namespace internal
struct StorageTagBitField;
struct VTKM_CONT_EXPORT BitFieldMetaData : vtkm::cont::internal::BufferMetaData
struct VTKM_CONT_EXPORT BufferMetaDataBitField : vtkm::cont::internal::BufferMetaData
{
vtkm::Id NumberOfBits = 0;
VTKM_CONT ~BitFieldMetaData() override;
VTKM_CONT ~BufferMetaDataBitField() override;
VTKM_CONT std::unique_ptr<vtkm::cont::internal::BufferMetaData> DeepCopy() const override;
};
@ -99,7 +99,7 @@ struct BitCoordinate
vtkm::Int32 BitOffset; // [0, bitsInWord)
};
VTKM_CONT_EXPORT vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
VTKM_CONT_EXPORT vtkm::cont::internal::BufferMetaDataBitField* GetBitFieldMetaData(
const vtkm::cont::internal::Buffer& buffer);
/// Portal for performing bit or word operations on a BitField.

@ -109,7 +109,6 @@ set(headers
Serialization.h
Storage.h
StorageExtrude.h
StorageImplicit.h
StorageList.h
StorageListTag.h
Timer.h
@ -137,6 +136,7 @@ set(template_sources
set(sources
ArrayHandle.cxx
ArrayHandleBasic.cxx
ArrayHandleImplicit.cxx
ArrayHandleSOA.cxx
BitField.cxx
ColorTablePresets.cxx

@ -1,177 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_cont_StorageImplicit
#define vtk_m_cont_StorageImplicit
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/Token.h>
#include <vtkm/cont/internal/ArrayTransfer.h>
namespace vtkm
{
namespace cont
{
/// \brief An implementation for read-only implicit arrays.
///
/// It is sometimes the case that you want VTK-m to operate on an array of
/// implicit values. That is, rather than store the data in an actual array, it
/// is gerenated on the fly by a function. This is handled in VTK-m by creating
/// an ArrayHandle in VTK-m with a StorageTagImplicit type of \c Storage. This
/// tag itself is templated to specify an ArrayPortal that generates the
/// desired values. An ArrayHandle created with this tag will raise an error on
/// any operation that tries to modify it.
///
template <class ArrayPortalType>
struct VTKM_ALWAYS_EXPORT StorageTagImplicit
{
using PortalType = ArrayPortalType;
};
namespace internal
{
template <class ArrayPortalType>
class VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{
using ClassType =
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>;
public:
using ValueType = typename ArrayPortalType::ValueType;
using PortalConstType = ArrayPortalType;
// Note that this portal is likely to be read-only, so you will probably get an error
// if you try to write to it.
using PortalType = ArrayPortalType;
VTKM_CONT
Storage(const PortalConstType& portal = PortalConstType())
: Portal(portal)
, NumberOfValues(portal.GetNumberOfValues())
{
}
VTKM_CONT Storage(const ClassType&) = default;
VTKM_CONT Storage(ClassType&&) = default;
VTKM_CONT ClassType& operator=(const ClassType&) = default;
VTKM_CONT ClassType& operator=(ClassType&&) = default;
// All these methods do nothing but raise errors.
VTKM_CONT
PortalType GetPortal() { throw vtkm::cont::ErrorBadValue("Implicit arrays are read-only."); }
VTKM_CONT
PortalConstType GetPortalConst() const { return this->Portal; }
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
VTKM_CONT
void Allocate(vtkm::Id numberOfValues)
{
VTKM_ASSERT(numberOfValues <= this->Portal.GetNumberOfValues());
this->NumberOfValues = numberOfValues;
}
VTKM_CONT
void Shrink(vtkm::Id numberOfValues)
{
VTKM_ASSERT(numberOfValues <= this->Portal.GetNumberOfValues());
this->NumberOfValues = numberOfValues;
}
VTKM_CONT
void ReleaseResources() {}
private:
PortalConstType Portal;
vtkm::Id NumberOfValues;
};
template <typename T, class ArrayPortalType, class DeviceAdapterTag>
class ArrayTransfer<T, StorageTagImplicit<ArrayPortalType>, DeviceAdapterTag>
{
public:
using StorageTag = StorageTagImplicit<ArrayPortalType>;
using StorageType = vtkm::cont::internal::Storage<T, StorageTag>;
using ValueType = T;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
using PortalExecution = PortalControl;
using PortalConstExecution = PortalConstControl;
VTKM_CONT
ArrayTransfer(StorageType* storage)
: Storage(storage)
{
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token&)
{
return this->Storage->GetPortalConst();
}
#if defined(VTKM_GCC) && defined(VTKM_ENABLE_OPENMP) && (__GNUC__ == 6 && __GNUC_MINOR__ == 1)
// When using GCC 6.1 with OpenMP enabled we cause a compiler ICE that is
// an identified compiler regression (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71210)
// The easiest way to work around this is to make sure we aren't building with >= O2
#define NO_OPTIMIZE_FUNC_ATTRIBUTE __attribute__((optimize(1)))
#else // gcc 6.1 openmp compiler ICE workaround
#define NO_OPTIMIZE_FUNC_ATTRIBUTE
#endif
VTKM_CONT
NO_OPTIMIZE_FUNC_ATTRIBUTE
PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData), vtkm::cont::Token&)
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be used for output or in place.");
}
VTKM_CONT
NO_OPTIMIZE_FUNC_ATTRIBUTE
PortalExecution PrepareForOutput(vtkm::Id vtkmNotUsed(numberOfValues), vtkm::cont::Token&)
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be used for output.");
}
#undef NO_OPTIMIZE_FUNC_ATTRIBUTE
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(controlArray)) const
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be used for output.");
}
VTKM_CONT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorBadValue("Implicit arrays cannot be resized.");
}
VTKM_CONT
void ReleaseResources() {}
private:
StorageType* Storage;
};
} // namespace internal
}
} // namespace vtkm::cont
#endif //vtk_m_cont_StorageImplicit

@ -81,7 +81,6 @@ set(unit_tests
UnitTestRuntimeDeviceInformation.cxx
UnitTestRuntimeDeviceNames.cxx
UnitTestScopedRuntimeDeviceTracker.cxx
UnitTestStorageImplicit.cxx
UnitTestStorageList.cxx
UnitTestStorageListTag.cxx
UnitTestTimer.cxx

@ -18,57 +18,8 @@ namespace UnitTestArrayHandleCountingNamespace
const vtkm::Id ARRAY_SIZE = 10;
// An unusual data type that represents a number with a string of a
// particular length. This makes sure that the ArrayHandleCounting
// works correctly with type casts.
class StringInt
{
public:
StringInt() {}
StringInt(vtkm::Id v)
{
VTKM_ASSERT(v >= 0);
for (vtkm::Id i = 0; i < v; i++)
{
++(*this);
}
}
operator vtkm::Id() const { return vtkm::Id(this->Value.size()); }
StringInt operator+(const StringInt& rhs) const { return StringInt(this->Value + rhs.Value); }
StringInt operator*(const StringInt& rhs) const
{
StringInt result;
for (vtkm::Id i = 0; i < rhs; i++)
{
result = result + *this;
}
return result;
}
bool operator==(const StringInt& other) const { return this->Value.size() == other.Value.size(); }
StringInt& operator++()
{
this->Value.append(".");
return *this;
}
private:
StringInt(const std::string& v)
: Value(v)
{
}
std::string Value;
};
} // namespace UnitTestArrayHandleCountingNamespace
VTKM_BASIC_TYPE_VECTOR(UnitTestArrayHandleCountingNamespace::StringInt)
namespace UnitTestArrayHandleCountingNamespace
{
@ -81,7 +32,7 @@ struct TemplatedTests
using PortalType =
typename vtkm::cont::internal::Storage<ValueType,
typename ArrayHandleType::StorageTag>::PortalConstType;
typename ArrayHandleType::StorageTag>::ReadPortalType;
void operator()(const ValueType& startingValue, const ValueType& step)
{
@ -90,7 +41,7 @@ struct TemplatedTests
ArrayHandleType arrayMake =
vtkm::cont::make_ArrayHandleCounting(startingValue, step, ARRAY_SIZE);
ArrayHandleType2 arrayHandle = ArrayHandleType2(PortalType(startingValue, step, ARRAY_SIZE));
ArrayHandleType2 arrayHandle = ArrayHandleType(startingValue, step, ARRAY_SIZE);
VTKM_TEST_ASSERT(arrayConst.GetNumberOfValues() == ARRAY_SIZE,
"Counting array using constructor has wrong size.");
@ -127,8 +78,6 @@ void TestArrayHandleCounting()
TemplatedTests<vtkm::Float32>()(3.0f, -0.5f);
TemplatedTests<vtkm::Float64>()(0.0, 1.0);
TemplatedTests<vtkm::Float64>()(-3.0, 2.0);
TemplatedTests<StringInt>()(StringInt(0), StringInt(1));
TemplatedTests<StringInt>()(StringInt(10), StringInt(2));
}

@ -1,134 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/Types.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageImplicit.h>
#include <vtkm/cont/internal/IteratorFromArrayPortal.h>
#include <vtkm/cont/testing/Testing.h>
#if defined(VTKM_STORAGE)
#undef VTKM_STORAGE
#endif
#define VTKM_STORAGE VTKM_STORAGE_ERROR
namespace
{
const vtkm::Id ARRAY_SIZE = 10;
template <typename T>
struct TestImplicitStorage
{
using ValueType = T;
ValueType Temp;
VTKM_EXEC_CONT
TestImplicitStorage()
: Temp(1)
{
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return ARRAY_SIZE; }
VTKM_EXEC_CONT
ValueType Get(vtkm::Id vtkmNotUsed(index)) const { return Temp; }
};
template <typename T>
struct TemplatedTests
{
using StorageTagType = vtkm::cont::StorageTagImplicit<TestImplicitStorage<T>>;
using StorageType = vtkm::cont::internal::Storage<T, StorageTagType>;
using ValueType = typename StorageType::ValueType;
using PortalType = typename StorageType::PortalType;
void BasicAllocation()
{
StorageType arrayStorage;
// The implicit portal defined for this test always returns ARRAY_SIZE for the
// number of values. We should get that.
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE,
"Implicit Storage GetNumberOfValues returned wrong size.");
// Make sure you can allocate and shrink to any value <= the reported portal size.
arrayStorage.Allocate(ARRAY_SIZE / 2);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE / 2,
"Cannot re-Allocate array to half size.");
arrayStorage.Allocate(0);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == 0, "Cannot re-Allocate array to zero.");
arrayStorage.Allocate(ARRAY_SIZE);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE,
"Cannot re-Allocate array to original size.");
arrayStorage.Shrink(ARRAY_SIZE / 2);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE / 2,
"Cannot Shrink array to half size.");
arrayStorage.Shrink(0);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == 0, "Cannot Shrink array to zero.");
arrayStorage.Shrink(ARRAY_SIZE);
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == ARRAY_SIZE,
"Cannot Shrink array to original size.");
//verify that calling ReleaseResources doesn't throw an exception
arrayStorage.ReleaseResources();
//verify that you can allocate after releasing resources.
arrayStorage.Allocate(ARRAY_SIZE);
}
void BasicAccess()
{
TestImplicitStorage<T> portal;
vtkm::cont::ArrayHandle<T, StorageTagType> implictHandle(portal);
VTKM_TEST_ASSERT(implictHandle.GetNumberOfValues() == ARRAY_SIZE, "handle has wrong size");
VTKM_TEST_ASSERT(implictHandle.ReadPortal().Get(0) == T(1), "portals first values should be 1");
}
void operator()()
{
BasicAllocation();
BasicAccess();
}
};
struct TestFunctor
{
template <typename T>
void operator()(T) const
{
TemplatedTests<T> tests;
tests();
}
};
void TestStorageBasic()
{
vtkm::testing::Testing::TryTypes(TestFunctor());
}
} // Anonymous namespace
int UnitTestStorageImplicit(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestStorageBasic, argc, argv);
}

@ -43,25 +43,6 @@ public:
{
}
VTKM_EXEC_CONT
ArrayPortalUniformPointCoordinates(const ArrayPortalUniformPointCoordinates& src)
: Dimensions(src.Dimensions)
, NumberOfValues(src.NumberOfValues)
, Origin(src.Origin)
, Spacing(src.Spacing)
{
}
VTKM_EXEC_CONT
ArrayPortalUniformPointCoordinates& operator=(const ArrayPortalUniformPointCoordinates& src)
{
this->Dimensions = src.Dimensions;
this->NumberOfValues = src.NumberOfValues;
this->Origin = src.Origin;
this->Spacing = src.Spacing;
return *this;
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }