Refactor vtkm::cont::ArrayHandleAny into vtkm::cont::ArrayHandleVirtual

ArrayHandleVirtual can automatically be constructed from any ArrayHandle.
In the cases where the input ArrayHandle doesn't derived from ArrayHandleVirtual,
it will automatically construct StorageAny to hold the array.
This commit is contained in:
Robert Maynard 2018-12-24 14:29:12 -05:00
parent 7a5e32be73
commit 3445047f9e
17 changed files with 542 additions and 340 deletions

@ -1,237 +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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_ArrayHandleAny_h
#define vtk_m_cont_ArrayHandleAny_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
namespace vtkm
{
namespace cont
{
template <typename T, typename S>
class VTKM_ALWAYS_EXPORT StorageAny final : public vtkm::cont::StorageVirtual
{
public:
VTKM_CONT
StorageAny(const vtkm::cont::ArrayHandle<T, S>& ah);
VTKM_CONT
~StorageAny() = default;
const vtkm::cont::ArrayHandle<T, S>& GetHandle() const { return this->Handle; }
vtkm::Id GetNumberOfValues() const { return this->Handle.GetNumberOfValues(); }
void ReleaseResourcesExecution();
void ReleaseResources();
private:
std::unique_ptr<StorageVirtual> MakeNewInstance() const
{
return std::unique_ptr<StorageVirtual>(new StorageAny<T, S>{ vtkm::cont::ArrayHandle<T, S>{} });
}
void ControlPortalForInput(vtkm::cont::internal::TransferInfoArray& payload) const;
void ControlPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload);
void TransferPortalForInput(vtkm::cont::internal::TransferInfoArray& payload,
vtkm::cont::DeviceAdapterId devId) const;
void TransferPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload,
OutputMode mode,
vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId);
vtkm::cont::ArrayHandle<T, S> Handle;
};
/// ArrayHandleAny is a specialization of ArrayHandle.
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleAny final : public vtkm::cont::ArrayHandleVirtual<T>
{
public:
///construct a valid ArrayHandleAny from an existing ArrayHandle
template <typename S>
VTKM_CONT ArrayHandleAny(const vtkm::cont::ArrayHandle<T, S>& ah)
: vtkm::cont::ArrayHandleVirtual<T>(std::make_shared<StorageAny<T, S>>(ah))
{
}
///construct an invalid ArrayHandleAny that has a nullptr storage
VTKM_CONT ArrayHandleAny()
: vtkm::cont::ArrayHandleVirtual<T>()
{
}
~ArrayHandleAny() = default;
};
/// A convenience function for creating an ArrayHandleAny.
template <typename T>
VTKM_CONT vtkm::cont::ArrayHandleAny<T> make_ArrayHandleAny(const vtkm::cont::ArrayHandle<T>& ah)
{
return vtkm::cont::ArrayHandleAny<T>(ah);
}
template <typename Functor, typename... Args>
void CastAndCall(vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>> coords,
Functor&& f,
Args&&... args)
{
using HandleType = ArrayHandleUniformPointCoordinates;
using T = typename HandleType::ValueType;
using S = typename HandleType::StorageTag;
if (coords.IsType<HandleType>())
{
const vtkm::cont::StorageVirtual* storage = coords.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
f(any->GetHandle(), std::forward<Args>(args)...);
}
else
{
f(coords, std::forward<Args>(args)...);
}
}
//=============================================================================
// Specializations of serialization related classes
template <typename T>
struct TypeString<vtkm::cont::ArrayHandleAny<T>>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "AH_Any<" + TypeString<T>::Get() + ">";
return name;
}
};
}
} //namespace vtkm::cont
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
//=============================================================================
// Specializations of serialization related classes
namespace diy
{
template <typename T>
struct Serialization<vtkm::cont::ArrayHandleAny<T>>
{
static VTKM_CONT void save(diy::BinaryBuffer& bb, const vtkm::cont::ArrayHandleAny<T>& obj)
{
vtkm::cont::internal::ArrayHandleDefaultSerialization(bb, obj);
}
static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::ArrayHandleAny<T>& obj)
{
vtkm::cont::ArrayHandle<T> array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleAny<T>{ array });
}
};
template <typename T>
struct IntAnySerializer
{
using CountingType = vtkm::cont::ArrayHandleCounting<T>;
using ConstantType = vtkm::cont::ArrayHandleConstant<T>;
using BasicType = vtkm::cont::ArrayHandle<T>;
static VTKM_CONT void save(diy::BinaryBuffer& bb, const vtkm::cont::ArrayHandleAny<T>& obj)
{
if (obj.template IsType<CountingType>())
{
diy::save(bb, vtkm::cont::TypeString<CountingType>::Get());
using S = typename CountingType::StorageTag;
const vtkm::cont::StorageVirtual* storage = obj.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
diy::save(bb, any->GetHandle());
}
else if (obj.template IsType<ConstantType>())
{
diy::save(bb, vtkm::cont::TypeString<ConstantType>::Get());
using S = typename ConstantType::StorageTag;
const vtkm::cont::StorageVirtual* storage = obj.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
diy::save(bb, any->GetHandle());
}
else
{
diy::save(bb, vtkm::cont::TypeString<BasicType>::Get());
vtkm::cont::internal::ArrayHandleDefaultSerialization(bb, obj);
}
}
static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::ArrayHandleAny<T>& obj)
{
std::string typeString;
diy::load(bb, typeString);
if (typeString == vtkm::cont::TypeString<CountingType>::Get())
{
CountingType array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleAny<T>{ array });
}
else if (typeString == vtkm::cont::TypeString<ConstantType>::Get())
{
ConstantType array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleAny<T>{ array });
}
else
{
vtkm::cont::ArrayHandle<T> array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleAny<T>{ array });
}
}
};
template <>
struct Serialization<vtkm::cont::ArrayHandleAny<vtkm::UInt8>> : public IntAnySerializer<vtkm::UInt8>
{
};
template <>
struct Serialization<vtkm::cont::ArrayHandleAny<vtkm::Int32>> : public IntAnySerializer<vtkm::Int32>
{
};
template <>
struct Serialization<vtkm::cont::ArrayHandleAny<vtkm::Int64>> : public IntAnySerializer<vtkm::Int64>
{
};
}
#endif //vtk_m_cont_ArrayHandleAny_h

@ -23,8 +23,10 @@
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/StorageAny.h>
#include <vtkm/cont/StorageVirtual.h>
#include <memory>
@ -55,9 +57,38 @@ public:
using PortalConst = vtkm::ArrayPortalRef<T>;
};
///construct an invlaid virtual array handle that has a nullptr storage
ArrayHandle()
: Storage(nullptr){};
///Construct a invalid ArrayHandleVirtual that has nullptr storage
VTKM_CONT ArrayHandle()
: Storage(nullptr)
{
}
///Construct a valid ArrayHandleVirtual from an existing ArrayHandle
///that doesn't derive from ArrayHandleVirtual.
///Note left non-explicit to allow:
///
/// std::vector<vtkm::cont::ArrayHandleVirtual<vtkm::Float64>> vectorOfArrays;
/// //Make basic array.
/// vtkm::cont::ArrayHandle<vtkm::Float64> basicArray;
/// //Fill basicArray...
/// vectorOfArrays.push_back(basicArray);
///
/// // Make fancy array.
/// vtkm::cont::ArrayHandleCounting<vtkm::Float64> fancyArray(-1.0, 0.1, ARRAY_SIZE);
/// vectorOfArrays.push_back(fancyArray);
template <typename S>
ArrayHandle(const vtkm::cont::ArrayHandle<T, S>& ah)
: Storage(std::make_shared<vtkm::cont::StorageAny<T, S>>(ah))
{
using is_base = std::is_base_of<vtkm::cont::StorageVirtual, S>;
static_assert(!is_base::value, "Wrong specialization for ArrayHandleVirtual selected");
}
///Copy an existing ArrayHandleVirtual into this instance
ArrayHandle(const ArrayHandle<T, vtkm::cont::StorageTagVirtual>& src) = default;
/// virtual destructor, as required to make sure derived classes that
@ -65,6 +96,7 @@ public:
//
virtual ~ArrayHandle() = default;
///Move existing shared_ptr of vtkm::cont::StorageVirtual to be
///owned by this ArrayHandleVirtual.
///This is generally how derived class construct a valid ArrayHandleVirtual
@ -89,23 +121,41 @@ public:
"Storage for ArrayHandleVirtual needs to derive from vtkm::cont::StorageVirual");
}
///copy another existing virtual array handle
ArrayHandle(const ArrayHandle<T, vtkm::cont::StorageTagVirtual>& src) = default;
///move from one virtual array handle to another
ArrayHandle(ArrayHandle<T, vtkm::cont::StorageTagVirtual>&& src) noexcept
: Storage(std::move(src.Storage))
{
}
///move from one a non-virtual array handle to virtual array handle
template <typename S>
ArrayHandle(ArrayHandle<T, S>&& src) noexcept
: Storage(std::make_shared<vtkm::cont::StorageAny<T, S>>(std::move(src)))
{
}
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(
const ArrayHandle<T, vtkm::cont::StorageTagVirtual>& src) = default;
template <typename S>
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(const ArrayHandle<T, S>& src)
{
this->Storage = std::make_shared<vtkm::cont::StorageAny<T, S>>(src);
return *this;
}
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(
ArrayHandle<T, vtkm::cont::StorageTagVirtual>&& src) noexcept
{
this->Storage = std::move(src.Storage);
return *this;
}
template <typename S>
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(
ArrayHandle<T, S>&& src) noexcept
{
this->Storage = std::make_shared<vtkm::cont::StorageAny<T, S>>(std::move(src));
return *this;
}
/// Like a pointer, two \c ArrayHandles are considered equal if they point
/// to the same location in memory.
@ -344,6 +394,15 @@ template <typename T>
using ArrayHandleVirtual = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>;
//=============================================================================
/// A convenience function for creating an ArrayHandleVirtual.
template <typename T, typename S>
VTKM_CONT vtkm::cont::ArrayHandleVirtual<T> make_ArrayHandleVirtual(
const vtkm::cont::ArrayHandle<T, S>& ah)
{
return vtkm::cont::ArrayHandleVirtual<T>(ah);
}
//=============================================================================
// Free function casting helpers
@ -359,6 +418,29 @@ VTKM_CONT inline ArrayHandleType Cast(const vtkm::cont::ArrayHandleVirtual<T>& v
return virtHandle.template Cast<ArrayHandleType>();
}
//=============================================================================
// Specializations of CastAndCall to help make sure ArrayHandleVirtual
// holding a ArrayHandleUniformPointCoordinates works properly
template <typename Functor, typename... Args>
void CastAndCall(vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>> coords,
Functor&& f,
Args&&... args)
{
using HandleType = ArrayHandleUniformPointCoordinates;
using T = typename HandleType::ValueType;
using S = typename HandleType::StorageTag;
if (coords.IsType<HandleType>())
{
const vtkm::cont::StorageVirtual* storage = coords.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
f(any->GetHandle(), std::forward<Args>(args)...);
}
else
{
f(coords, std::forward<Args>(args)...);
}
}
//=============================================================================

@ -21,8 +21,7 @@
#define vtk_m_cont_ArrayHandleVirtual_hxx
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/StorageAny.hxx>
#include <vtkm/cont/TryExecute.h>
namespace vtkm
@ -57,48 +56,12 @@ ArrayHandleType ArrayHandle<T, StorageTagVirtual>::CastToType(
const auto* any = this->Storage->template Cast<vtkm::cont::StorageAny<T, S>>();
return any->GetHandle();
}
namespace detail
{
template <typename DerivedPortal>
struct TransferToDevice
{
template <typename DeviceAdapterTag, typename Payload, typename... Args>
bool operator()(DeviceAdapterTag devId, Payload&& payload, Args&&... args) const
{
using TransferType = cont::internal::VirtualObjectTransfer<DerivedPortal, DeviceAdapterTag>;
//construct all new transfer payload
auto host = std::unique_ptr<DerivedPortal>(new DerivedPortal(std::forward<Args>(args)...));
auto transfer = std::make_shared<TransferType>(host.get());
auto device = transfer->PrepareForExecution(true);
payload.updateDevice(devId, std::move(host), device, std::static_pointer_cast<void>(transfer));
return true;
}
};
}
template <typename DerivedPortal, typename... Args>
inline void make_transferToDevice(vtkm::cont::DeviceAdapterId devId, Args&&... args)
{
vtkm::cont::TryExecuteOnDevice(
devId, detail::TransferToDevice<DerivedPortal>{}, std::forward<Args>(args)...);
}
template <typename DerivedPortal, typename Payload, typename... Args>
inline void make_hostPortal(Payload&& payload, Args&&... args)
{
auto host = std::unique_ptr<DerivedPortal>(new DerivedPortal(std::forward<Args>(args)...));
payload.updateHost(std::move(host));
}
}
} // namespace vtkm::virts
} // namespace vtkm::const
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
//=============================================================================
// Specializations of serialization related classes
@ -108,19 +71,46 @@ namespace diy
template <typename T>
struct Serialization<vtkm::cont::ArrayHandleVirtual<T>>
{
private:
using Type = vtkm::cont::ArrayHandleVirtual<T>;
using BaseType = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>;
static VTKM_CONT void save(diy::BinaryBuffer& bb, const vtkm::cont::ArrayHandleVirtual<T>& obj)
{
vtkm::cont::internal::ArrayHandleDefaultSerialization(bb, obj);
}
static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::ArrayHandleVirtual<T>& obj)
{
vtkm::cont::ArrayHandle<T> array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleVirtual<T>{ array });
}
};
template <typename T>
struct IntAnySerializer
{
using CountingType = vtkm::cont::ArrayHandleCounting<T>;
using ConstantType = vtkm::cont::ArrayHandleConstant<T>;
using BasicType = vtkm::cont::ArrayHandle<T>;
public:
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
static VTKM_CONT void save(diy::BinaryBuffer& bb, const vtkm::cont::ArrayHandleVirtual<T>& obj)
{
if (obj.template IsType<vtkm::cont::ArrayHandleAny<T>>())
if (obj.template IsType<CountingType>())
{
const auto& array = static_cast<const vtkm::cont::ArrayHandleAny<T>&>(obj);
diy::save(bb, vtkm::cont::TypeString<vtkm::cont::ArrayHandleAny<T>>::Get());
diy::save(bb, array);
diy::save(bb, vtkm::cont::TypeString<CountingType>::Get());
using S = typename CountingType::StorageTag;
const vtkm::cont::StorageVirtual* storage = obj.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
diy::save(bb, any->GetHandle());
}
else if (obj.template IsType<ConstantType>())
{
diy::save(bb, vtkm::cont::TypeString<ConstantType>::Get());
using S = typename ConstantType::StorageTag;
const vtkm::cont::StorageVirtual* storage = obj.GetStorage();
auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
diy::save(bb, any->GetHandle());
}
else
{
@ -129,31 +119,48 @@ public:
}
}
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::ArrayHandleVirtual<T>& obj)
{
std::string typeString;
diy::load(bb, typeString);
if (typeString == vtkm::cont::TypeString<vtkm::cont::ArrayHandleAny<T>>::Get())
if (typeString == vtkm::cont::TypeString<CountingType>::Get())
{
vtkm::cont::ArrayHandleAny<T> array;
CountingType array;
diy::load(bb, array);
obj = std::move(array);
obj = std::move(vtkm::cont::ArrayHandleVirtual<T>{ array });
}
else if (typeString == vtkm::cont::TypeString<BasicType>::Get())
else if (typeString == vtkm::cont::TypeString<ConstantType>::Get())
{
BasicType array;
ConstantType array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleAny<T>{ array });
obj = std::move(vtkm::cont::ArrayHandleVirtual<T>{ array });
}
else
{
throw vtkm::cont::ErrorBadType("Error deserializing ArrayHandleVirtual. TypeString: " +
typeString);
vtkm::cont::ArrayHandle<T> array;
diy::load(bb, array);
obj = std::move(vtkm::cont::ArrayHandleVirtual<T>{ array });
}
}
};
template <>
struct Serialization<vtkm::cont::ArrayHandleVirtual<vtkm::UInt8>>
: public IntAnySerializer<vtkm::UInt8>
{
};
template <>
struct Serialization<vtkm::cont::ArrayHandleVirtual<vtkm::Int32>>
: public IntAnySerializer<vtkm::Int32>
{
};
template <>
struct Serialization<vtkm::cont::ArrayHandleVirtual<vtkm::Int64>>
: public IntAnySerializer<vtkm::Int64>
{
};
}
#endif

@ -20,7 +20,6 @@
#ifndef vtk_m_cont_ArrayHandleVirtualCoordinates_h
#define vtk_m_cont_ArrayHandleVirtualCoordinates_h
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
@ -64,8 +63,7 @@ public:
template <typename S>
explicit ArrayHandleVirtualCoordinates(const vtkm::cont::ArrayHandle<ValueType, S>& ah)
: vtkm::cont::ArrayHandleVirtual<ValueType>(
std::make_shared<vtkm::cont::StorageAny<ValueType, S>>(ah))
: vtkm::cont::ArrayHandleVirtual<ValueType>(ah)
{
}

@ -97,10 +97,10 @@ VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 4, vtkm::cont::StorageTagBasi
#undef VTKM_ARRAY_RANGE_COMPUTE_EXPORT_T
#undef VTKM_ARRAY_RANGE_COMPUTE_EXPORT_VEC
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
const vtkm::cont::ArrayHandleVirtualCoordinates& input,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker());
// VTKM_CONT
// vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
// const vtkm::cont::ArrayHandleVirtualCoordinates& input,
// vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker());
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(

@ -104,15 +104,15 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeImpl(
} // namespace detail
VTKM_CONT
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
const vtkm::cont::ArrayHandleVirtualCoordinates& input,
vtkm::cont::RuntimeDeviceTracker tracker)
{
auto array =
static_cast<const vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>>&>(input);
return ArrayRangeCompute(array, tracker);
}
// VTKM_CONT
// inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
// const vtkm::cont::ArrayHandleVirtualCoordinates& input,
// vtkm::cont::RuntimeDeviceTracker tracker)
// {
// auto array =
// static_cast<const vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>>&>(input);
// return ArrayRangeCompute(array, tracker);
// }
VTKM_CONT
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
@ -125,7 +125,6 @@ inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>;
if (input.IsType<UniformHandleType>())
{
using T = typename UniformHandleType::ValueType;

@ -22,7 +22,6 @@ set(headers
Algorithm.h
ArrayCopy.h
ArrayHandle.h
ArrayHandleAny.h
ArrayHandleCartesianProduct.h
ArrayHandleCast.h
ArrayHandleCompositeVector.h
@ -99,6 +98,7 @@ set(headers
RuntimeDeviceTracker.h
Serialization.h
Storage.h
StorageAny.h
StorageBasic.h
StorageImplicit.h
StorageListTag.h
@ -112,7 +112,6 @@ set(headers
set(template_sources
ArrayHandle.hxx
ArrayHandleAny.hxx
ArrayHandleVirtual.hxx
ArrayRangeCompute.hxx
BoundingIntervalHierarchy.hxx
@ -122,7 +121,9 @@ set(template_sources
CoordinateSystem.hxx
FieldRangeCompute.hxx
FieldRangeGlobalCompute.hxx
StorageAny.hxx
StorageBasic.hxx
StorageVirtual.hxx
)
set(sources

74
vtkm/cont/StorageAny.h Normal file

@ -0,0 +1,74 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_StorageAny_h
#define vtk_m_cont_StorageAny_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageVirtual.h>
namespace vtkm
{
namespace cont
{
template <typename T, typename S>
class VTKM_ALWAYS_EXPORT StorageAny final : public vtkm::cont::StorageVirtual
{
public:
VTKM_CONT
explicit StorageAny(const vtkm::cont::ArrayHandle<T, S>& ah);
explicit StorageAny(vtkm::cont::ArrayHandle<T, S>&& ah) noexcept;
VTKM_CONT
~StorageAny() = default;
const vtkm::cont::ArrayHandle<T, S>& GetHandle() const { return this->Handle; }
vtkm::Id GetNumberOfValues() const { return this->Handle.GetNumberOfValues(); }
void ReleaseResourcesExecution();
void ReleaseResources();
private:
std::unique_ptr<StorageVirtual> MakeNewInstance() const
{
return std::unique_ptr<StorageVirtual>(new StorageAny<T, S>{ vtkm::cont::ArrayHandle<T, S>{} });
}
void ControlPortalForInput(vtkm::cont::internal::TransferInfoArray& payload) const;
void ControlPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload);
void TransferPortalForInput(vtkm::cont::internal::TransferInfoArray& payload,
vtkm::cont::DeviceAdapterId devId) const;
void TransferPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload,
OutputMode mode,
vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId);
vtkm::cont::ArrayHandle<T, S> Handle;
};
}
}
#endif //vtk_m_cont_StorageAny_h

@ -17,11 +17,11 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_ArrayHandleAny_hxx
#define vtk_m_cont_ArrayHandleAny_hxx
#ifndef vtk_m_cont_StorageAny_hxx
#define vtk_m_cont_StorageAny_hxx
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/ArrayHandleVirtual.hxx>
#include <vtkm/cont/StorageAny.h>
#include <vtkm/cont/StorageVirtual.hxx>
namespace vtkm
{
@ -36,6 +36,14 @@ StorageAny<T, S>::StorageAny(const vtkm::cont::ArrayHandle<T, S>& ah)
{
}
VTKM_CONT
template <typename T, typename S>
StorageAny<T, S>::StorageAny(vtkm::cont::ArrayHandle<T, S>&& ah) noexcept
: vtkm::cont::StorageVirtual(),
Handle(std::move(ah))
{
}
/// release execution side resources
template <typename T, typename S>
void StorageAny<T, S>::ReleaseResourcesExecution()
@ -151,4 +159,4 @@ void StorageAny<T, S>::TransferPortalForOutput(vtkm::cont::internal::TransferInf
}
} // namespace vtkm::cont
#endif //vtk_m_cont_ArrayHandleAny_hxx
#endif //vtk_m_cont_StorageAny_hxx

@ -0,0 +1,71 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_StorageVirtual_hxx
#define vtk_m_cont_StorageVirtual_hxx
#include <vtkm/cont/StorageAny.hxx>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/TransferInfo.h>
namespace vtkm
{
namespace cont
{
namespace detail
{
template <typename DerivedPortal>
struct TransferToDevice
{
template <typename DeviceAdapterTag, typename Payload, typename... Args>
bool operator()(DeviceAdapterTag devId, Payload&& payload, Args&&... args) const
{
using TransferType = cont::internal::VirtualObjectTransfer<DerivedPortal, DeviceAdapterTag>;
//construct all new transfer payload
auto host = std::unique_ptr<DerivedPortal>(new DerivedPortal(std::forward<Args>(args)...));
auto transfer = std::make_shared<TransferType>(host.get());
auto device = transfer->PrepareForExecution(true);
payload.updateDevice(devId, std::move(host), device, std::static_pointer_cast<void>(transfer));
return true;
}
};
}
template <typename DerivedPortal, typename... Args>
inline void make_transferToDevice(vtkm::cont::DeviceAdapterId devId, Args&&... args)
{
vtkm::cont::TryExecuteOnDevice(
devId, detail::TransferToDevice<DerivedPortal>{}, std::forward<Args>(args)...);
}
template <typename DerivedPortal, typename Payload, typename... Args>
inline void make_hostPortal(Payload&& payload, Args&&... args)
{
auto host = std::unique_ptr<DerivedPortal>(new DerivedPortal(std::forward<Args>(args)...));
payload.updateHost(std::move(host));
}
}
} // namespace vtkm::cont::
#endif

@ -77,7 +77,7 @@ public:
template <typename T, typename Storage>
VTKM_CONT VariantArrayHandleBase(const vtkm::cont::ArrayHandle<T, Storage>& array)
: ArrayContainer(std::make_shared<internal::VariantArrayHandleContainer<T>>(
vtkm::cont::ArrayHandleAny<T>{ array }))
vtkm::cont::ArrayHandleVirtual<T>{ array }))
{
}

@ -23,7 +23,7 @@
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/StorageBasic.h>
#include <vtkm/cont/StorageVirtual.h>

@ -25,7 +25,6 @@
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/ArrayHandleVirtual.hxx>
#include <vtkm/cont/ArrayHandleAny.hxx>
#include <memory>
#include <vtkm/Types.h>
@ -171,7 +170,7 @@ struct VTKM_ALWAYS_EXPORT Caster
}
//we know the storage isn't a virtual but another storage type
//that means that the container holds a vtkm::cont::ArrayHandleAny<T>
//that means that the container holds a vtkm::cont::StorageAny<T>
const auto* any = static_cast<const vtkm::cont::StorageAny<T, S>*>(container->GetStorage());
VTKM_LOG_CAST_SUCC(container, *any);
return any->GetHandle();

@ -55,6 +55,7 @@ set(unit_tests
UnitTestArrayHandleTransform.cxx
UnitTestArrayHandleUniformPointCoordinates.cxx
UnitTestArrayHandleConcatenate.cxx
UnitTestArrayHandleVirtual.cxx
UnitTestVariantArrayHandle.cxx
UnitTestArrayPortalToIterators.cxx
UnitTestCellLocator.cxx

@ -0,0 +1,208 @@
//============================================================================
// 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.
//
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2017 UT-Battelle, LLC.
// Copyright 2017 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/serial/internal/ArrayManagerExecutionSerial.h>
#include <vtkm/cont/serial/internal/DeviceAdapterAlgorithmSerial.h>
#include <vtkm/cont/serial/internal/DeviceAdapterTagSerial.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/BinaryOperators.h>
#include <algorithm>
namespace UnitTestArrayHandleVirtualDetail
{
template <typename ValueType>
struct Test
{
static constexpr vtkm::Id ARRAY_SIZE = 100;
static constexpr vtkm::Id NUM_KEYS = 3;
using ArrayHandle = vtkm::cont::ArrayHandle<ValueType>;
using VirtHandle = vtkm::cont::ArrayHandleVirtual<ValueType>;
using DeviceTag = vtkm::cont::DeviceAdapterTagSerial;
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceTag>;
void TestConstructors()
{
VirtHandle nullStorage;
VTKM_TEST_ASSERT(nullStorage.GetStorage() == nullptr,
"storage should be empty when using ArrayHandleVirtual().");
VirtHandle fromArrayHandle{ ArrayHandle{} };
VTKM_TEST_ASSERT(fromArrayHandle.GetStorage() != nullptr,
"storage should be empty when using ArrayHandleVirtual().");
VTKM_TEST_ASSERT(vtkm::cont::IsType<ArrayHandle>(fromArrayHandle),
"ArrayHandleVirtual should contain a ArrayHandle<ValueType>.");
VirtHandle fromVirtHandle(fromArrayHandle);
VTKM_TEST_ASSERT(fromVirtHandle.GetStorage() != nullptr,
"storage should be empty when using ArrayHandleVirtual().");
VTKM_TEST_ASSERT(vtkm::cont::IsType<ArrayHandle>(fromVirtHandle),
"ArrayHandleVirtual should contain a ArrayHandle<ValueType>.");
VirtHandle fromNullPtrHandle(nullStorage);
VTKM_TEST_ASSERT(fromNullPtrHandle.GetStorage() == nullptr,
"storage should be empty when constructing from a ArrayHandleVirtual that has "
"nullptr storage.");
VTKM_TEST_ASSERT((vtkm::cont::IsType<ArrayHandle>(fromNullPtrHandle) == false),
"ArrayHandleVirtual shouldn't match any type with nullptr storage.");
}
void TestMoveConstructors()
{
//test shared_ptr move constructor
{
vtkm::cont::ArrayHandleCounting<ValueType> countingHandle;
using ST = typename decltype(countingHandle)::StorageTag;
auto sharedPtr = std::make_shared<vtkm::cont::StorageAny<ValueType, ST>>(countingHandle);
VirtHandle virt(std::move(sharedPtr));
VTKM_TEST_ASSERT(
vtkm::cont::IsType<decltype(countingHandle)>(virt),
"ArrayHandleVirtual should be valid after move constructor shared_ptr<Storage>.");
}
//test unique_ptr move constructor
{
vtkm::cont::ArrayHandleCounting<ValueType> countingHandle;
using ST = typename decltype(countingHandle)::StorageTag;
auto uniquePtr = std::unique_ptr<vtkm::cont::StorageAny<ValueType, ST>>(
new vtkm::cont::StorageAny<ValueType, ST>(countingHandle));
VirtHandle virt(std::move(uniquePtr));
VTKM_TEST_ASSERT(
vtkm::cont::IsType<decltype(countingHandle)>(virt),
"ArrayHandleVirtual should be valid after move constructor unique_ptr<Storage>.");
}
//test ArrayHandle move constructor
{
ArrayHandle handle;
VirtHandle virt(std::move(handle));
VTKM_TEST_ASSERT(
vtkm::cont::IsType<ArrayHandle>(virt),
"ArrayHandleVirtual should be valid after move constructor ArrayHandle<ValueType>.");
}
//test ArrayHandleVirtual move constructor
{
ArrayHandle handle;
VirtHandle virt(std::move(handle));
VirtHandle virt2(std::move(virt));
VTKM_TEST_ASSERT(
vtkm::cont::IsType<ArrayHandle>(virt2),
"ArrayHandleVirtual should be valid after move constructor ArrayHandleVirtual<ValueType>.");
}
}
void TestAssignmentOps()
{
//test assignment operator from ArrayHandleVirtual
{
VirtHandle virt;
virt = VirtHandle{ ArrayHandle{} };
VTKM_TEST_ASSERT(vtkm::cont::IsType<ArrayHandle>(virt),
"ArrayHandleVirtual should be valid after assignment op from AHV.");
}
//test assignment operator from ArrayHandle
{
VirtHandle virt = vtkm::cont::ArrayHandleCounting<ValueType>{};
virt = ArrayHandle{};
VTKM_TEST_ASSERT(vtkm::cont::IsType<ArrayHandle>(virt),
"ArrayHandleVirtual should be valid after assignment op from AH.");
}
//test move assignment operator from ArrayHandleVirtual
{
VirtHandle temp{ ArrayHandle{} };
VirtHandle virt;
virt = std::move(temp);
VTKM_TEST_ASSERT(vtkm::cont::IsType<ArrayHandle>(virt),
"ArrayHandleVirtual should be valid after move assignment op from AHV.");
}
//test move assignment operator from ArrayHandle
{
vtkm::cont::ArrayHandleCounting<ValueType> temp;
VirtHandle virt;
virt = std::move(temp);
VTKM_TEST_ASSERT(vtkm::cont::IsType<decltype(temp)>(virt),
"ArrayHandleVirtual should be valid after move assignment op from AH.");
}
}
void TestPrepareForExecution()
{
vtkm::cont::ArrayHandle<ValueType> handle;
handle.Allocate(50);
VirtHandle virt(std::move(handle));
try
{
virt.PrepareForInput(DeviceTag());
virt.PrepareForInPlace(DeviceTag());
virt.PrepareForOutput(ARRAY_SIZE, DeviceTag());
}
catch (vtkm::cont::ErrorBadValue&)
{
// un-expected failure.
VTKM_TEST_FAIL(
"Unexpected error when using Prepare* on an ArrayHandleVirtual with StorageAny.");
}
}
void operator()()
{
TestConstructors();
TestMoveConstructors();
TestAssignmentOps();
TestPrepareForExecution();
}
};
void TestArrayHandleVirtual()
{
Test<vtkm::UInt8>()();
Test<vtkm::Int16>()();
Test<vtkm::Int32>()();
Test<vtkm::Int64>()();
Test<vtkm::Float32>()();
Test<vtkm::Float64>()();
}
} // end namespace UnitTestArrayHandleVirtualDetail
int UnitTestArrayHandleVirtual(int, char* [])
{
using namespace UnitTestArrayHandleVirtualDetail;
return vtkm::cont::testing::Testing::Run(TestArrayHandleVirtual);
}

@ -18,7 +18,6 @@
// this software.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/ArrayHandleVirtualCoordinates.h>
#include <vtkm/cont/CellSetExplicit.h>
@ -34,7 +33,6 @@
namespace
{
// clang-format off
template<typename T>
void is_noexcept_movable()
@ -79,27 +77,21 @@ struct IsNoExceptHandle
void operator()(T) const
{
using HandleType = vtkm::cont::ArrayHandle<T>;
using AnyType = vtkm::cont::ArrayHandleAny<T>;
using VirtualType = vtkm::cont::ArrayHandleVirtual<T>;
//verify the handle type
is_noexcept_movable<HandleType>();
is_noexcept_movable<AnyType>();
is_noexcept_movable<VirtualType>();
//verify the input portals of the handle
is_noexcept_movable<decltype(
std::declval<HandleType>().PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{}))>();
is_noexcept_movable<decltype(
std::declval<AnyType>().PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{}))>();
is_noexcept_movable<decltype(
std::declval<VirtualType>().PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{}))>();
//verify the output portals of the handle
is_noexcept_movable<decltype(
std::declval<HandleType>().PrepareForOutput(2, vtkm::cont::DeviceAdapterTagSerial{}))>();
is_noexcept_movable<decltype(
std::declval<AnyType>().PrepareForOutput(2, vtkm::cont::DeviceAdapterTagSerial{}))>();
is_noexcept_movable<decltype(
std::declval<VirtualType>().PrepareForOutput(2, vtkm::cont::DeviceAdapterTagSerial{}))>();
}

@ -22,7 +22,6 @@
#include <vtkm/TypeTraits.h>
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleConstant.h>