Add StorageVirtual and ArrayHandleVirtual to vtkm::cont

This commit is contained in:
Robert Maynard 2018-11-06 11:20:30 -05:00
parent 20d02fdec2
commit 6e1cbaa16a
15 changed files with 1136 additions and 1 deletions

@ -58,6 +58,7 @@ set(headers
VecAxisAlignedPointCoordinates.h
VecFromPortal.h
VecFromPortalPermute.h
VecFromVirtPortal.h
VectorAnalysis.h
VecTraits.h
VecVariable.h

79
vtkm/VecFromVirtPortal.h Normal file

@ -0,0 +1,79 @@
//============================================================================
// 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 2015 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 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_VecFromVirtPortal_h
#define vtk_m_VecFromVirtPortal_h
#include <vtkm/Types.h>
#include <vtkm/VecFromPortal.h>
#include <vtkm/internal/ArrayPortalVirtual.h>
namespace vtkm
{
/// \brief A short variable-length array from a window in an ArrayPortal.
///
/// The \c VecFromPortal class is a Vec-like class that holds an array portal
/// and exposes a small window of that portal as if it were a \c Vec.
///
template <typename T>
class VTKM_ALWAYS_EXPORT VecFromVirtPortal
{
using RefType = vtkm::internal::ArrayPortalValueReference<vtkm::ArrayPortalRef<T>>;
public:
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
VecFromVirtPortal(const vtkm::ArrayPortalRef<T>* portal,
vtkm::IdComponent numComponents,
vtkm::Id offset)
: Portal(portal)
, NumComponents(numComponents)
, Offset(offset)
{
}
VTKM_EXEC_CONT
vtkm::IdComponent GetNumberOfComponents() const { return this->NumComponents; }
template <vtkm::IdComponent DestSize>
VTKM_EXEC_CONT void CopyInto(vtkm::Vec<T, DestSize>& dest) const
{
vtkm::IdComponent numComponents = vtkm::Min(DestSize, this->NumComponents);
for (vtkm::IdComponent index = 0; index < numComponents; index++)
{
dest[index] = this->Portal->Get(index + this->Offset);
}
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
RefType operator[](vtkm::IdComponent index) const
{
return RefType(*this->Portal, index + this->Offset);
}
private:
const vtkm::ArrayPortalRef<T>* Portal = nullptr;
vtkm::IdComponent NumComponents = 0;
vtkm::Id Offset = 0;
};
}
#endif

@ -0,0 +1,203 @@
//============================================================================
// 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_ArrayHandleVirtual_h
#define vtk_m_cont_ArrayHandleVirtual_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/StorageVirtual.h>
#include <memory>
namespace vtkm
{
namespace cont
{
/// Specialization of ArrayHandle for virtual storage.
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandle<T, ::vtkm::cont::StorageTagVirtual>
: public vtkm::cont::internal::ArrayHandleBase
{
public:
using StorageTag = vtkm::cont::StorageTagVirtual;
using StorageType = vtkm::cont::internal::Storage<void, vtkm::cont::StorageTagVirtual>;
using ValueType = T;
using PortalControl = vtkm::ArrayPortalRef<T>;
using PortalConstControl = vtkm::ArrayPortalRef<T>;
template <typename Device>
struct ExecutionTypes
{
using Portal = vtkm::ArrayPortalRef<T>;
using PortalConst = vtkm::ArrayPortalRef<T>;
};
///construct an invlaid virtual array handle that has a nullptr storage
ArrayHandle()
: Storage(nullptr){};
///Move existing shared_ptr of vtkm::cont::StorageVirtual to be
///owned by this ArrayHandleVirtual.
///This is generally how derived class construct a valid ArrayHandleVirtual
template <typename DerivedStorage>
explicit ArrayHandle(std::shared_ptr<DerivedStorage>&& storage) noexcept
: Storage(std::move(storage))
{
using is_base = std::is_base_of<vtkm::cont::StorageVirtual, DerivedStorage>;
static_assert(is_base::value,
"Storage for ArrayHandleVirtual needs to derive from vtkm::cont::StorageVirual");
}
///Move existing unique_ptr of vtkm::cont::StorageVirtual to be
///owned by this ArrayHandleVirtual.
///This is how a derived class construct a valid ArrayHandleVirtual
template <typename DerivedStorage>
explicit ArrayHandle(std::unique_ptr<DerivedStorage>&& storage) noexcept
: Storage(std::move(storage))
{
using is_base = std::is_base_of<vtkm::cont::StorageVirtual, DerivedStorage>;
static_assert(is_base::value,
"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))
{
}
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(
const ArrayHandle<T, vtkm::cont::StorageTagVirtual>& src) = default;
VTKM_CONT ArrayHandle<T, vtkm::cont::StorageTagVirtual>& operator=(
ArrayHandle<T, vtkm::cont::StorageTagVirtual>&& src) noexcept
{
this->Storage = std::move(src.Storage);
return *this;
}
/// Returns true if this array's storage matches the type passed in.
///
template <typename ArrayHandleType>
VTKM_CONT bool IsType() const
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
//We need to go long the way to find the StorageType
//as StorageType is private on lots of derived ArrayHandles
//See Issue #314
using VT = typename ArrayHandleType::ValueType;
static_assert(
std::is_same<VT, T>::value,
"ArrayHandleVirtual<ValueType> can only be casted to an ArrayHandle of the same ValueType.");
using ST = typename ArrayHandleType::StorageTag;
return this->Storage->IsType(typeid(vtkm::cont::internal::Storage<VT, ST>));
}
/// Returns a view on the internal storage of the ArrayHandleVirtual
///
VTKM_CONT const StorageType* GetStorage() const { return this->Storage.get(); }
/// Returns a new instance of an ArrayHandleVirtual with the same storage
///
VTKM_CONT ArrayHandle<T, ::vtkm::cont::StorageTagVirtual> NewInstance() const
{
return (this->Storage)
? ArrayHandle<T, ::vtkm::cont::StorageTagVirtual>(this->Storage->NewInstance())
: ArrayHandle<T, ::vtkm::cont::StorageTagVirtual>();
}
// Return a ArrayPortalRef that wraps the real virtual portal. We need a stack object for
// the following reasons:
// 1. Device Adapter algorithms only support const AH<T,S>& and not const AH<T,S>*
// 2. Devices will want to get the length of a portal before execution, but for CUDA
// we can't ask this information of the portal as it only valid on the device, instead
// we have to store this information also in the ref wrapper
vtkm::ArrayPortalRef<T> PrepareForInput(vtkm::cont::DeviceAdapterId devId) const
{
return make_ArrayPortalRef(
static_cast<const vtkm::ArrayPortalVirtual<T>*>(this->Storage->PrepareForInput(devId)),
this->GetNumberOfValues());
}
vtkm::ArrayPortalRef<T> PrepareForOutput(vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId)
{
return make_ArrayPortalRef(static_cast<const vtkm::ArrayPortalVirtual<T>*>(
this->Storage->PrepareForOutput(numberOfValues, devId)),
numberOfValues);
}
vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
/// Releases any resources being used in the execution environment (that are
/// not being shared by the control environment).
///
void ReleaseResourcesExecution() { return this->Storage->ReleaseResourcesExecution(); }
/// Releases all resources in both the control and execution environments.
///
void ReleaseResources() { return this->Storage->ReleaseResources(); }
/// Get the array portal of the control array.
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
/// exceptions maybe thrown for errors from previously executed worklets.
///
PortalControl GetPortalControl()
{
return make_ArrayPortalRef(
static_cast<const vtkm::ArrayPortalVirtual<T>*>(this->Storage->GetPortalControl()),
this->GetNumberOfValues());
}
/// Get the array portal of the control array.
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
/// exceptions maybe thrown for errors from previously executed worklets.
///
PortalConstControl GetPortalConstControl() const
{
return make_ArrayPortalRef(
static_cast<const vtkm::ArrayPortalVirtual<T>*>(this->Storage->GetPortalConstControl()),
this->GetNumberOfValues());
}
protected:
std::shared_ptr<StorageType> Storage = nullptr;
};
template <typename T>
using ArrayHandleVirtual = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>;
}
} //namespace vtkm::cont
#include <vtkm/cont/ArrayHandleAny.h>
#endif

@ -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_ArrayHandleVirtual_hxx
#define vtk_m_cont_ArrayHandleVirtual_hxx
#include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/TryExecute.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::virts
#endif

@ -40,6 +40,7 @@ set(headers
ArrayHandleTransform.h
ArrayHandleUniformPointCoordinates.h
ArrayHandleView.h
ArrayHandleVirtual.h
ArrayHandleVirtualCoordinates.h
ArrayHandleZip.h
ArrayPortal.h
@ -100,6 +101,7 @@ set(headers
Storage.h
StorageBasic.h
StorageImplicit.h
StorageVirtual.h
StorageListTag.h
Timer.h
TryExecute.h
@ -109,6 +111,7 @@ set(headers
set(template_sources
ArrayHandle.hxx
ArrayHandleVirtual.hxx
ArrayRangeCompute.hxx
BoundingIntervalHierarchy.hxx
CellSetExplicit.hxx
@ -136,6 +139,7 @@ set(sources
DynamicArrayHandle.cxx
EnvironmentTracker.cxx
ErrorBadDevice.cxx
ErrorBadType.cxx
Field.cxx
FieldRangeCompute.cxx
FieldRangeGlobalCompute.cxx
@ -143,7 +147,7 @@ set(sources
internal/ArrayManagerExecutionShareWithControl.cxx
internal/DeviceAdapterTag.cxx
internal/SimplePolymorphicContainer.cxx
internal/SimplePolymorphicContainer.cxx
internal/TransferInfo.cxx
internal/VirtualObjectTransfer.cxx
Initialize.cxx
Logging.cxx
@ -151,6 +155,7 @@ set(sources
RuntimeDeviceInformation.cxx
RuntimeDeviceTracker.cxx
StorageBasic.cxx
StorageVirtual.cxx
TryExecute.cxx
)

@ -0,0 +1,37 @@
//============================================================================
// 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 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 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/ErrorBadType.h>
#include <string>
namespace vtkm
{
namespace cont
{
void throwFailedDynamicCast(const std::string& baseType, const std::string& derivedType)
{ //Should we support typeid() instead of className?
const std::string msg = "Cast failed: " + baseType + " --> " + derivedType;
throw vtkm::cont::ErrorBadType(msg);
}
}
}

@ -42,6 +42,14 @@ public:
};
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
/// Throws an ErrorBadType exception with the following message:
/// Cast failed: \c baseType --> \c derivedType".
/// This is generally caused by asking for a casting of a ArrayHandleVariant
/// with an insufficient type list.
//
VTKM_CONT_EXPORT void throwFailedDynamicCast(const std::string& baseType,
const std::string& derivedType);
}
} // namespace vtkm::cont

@ -0,0 +1,211 @@
//============================================================================
// 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.
//============================================================================
#include "StorageVirtual.h"
#include <vtkm/cont/internal/DeviceAdapterError.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
//--------------------------------------------------------------------
Storage<void, ::vtkm::cont::StorageTagVirtual>::Storage(
const Storage<void, vtkm::cont::StorageTagVirtual>& src)
: HostUpToDate(src.HostUpToDate)
, DeviceUpToDate(src.DeviceUpToDate)
, DeviceTransferState(src.DeviceTransferState)
{
}
//--------------------------------------------------------------------
Storage<void, ::vtkm::cont::StorageTagVirtual>::Storage(
Storage<void, vtkm::cont::StorageTagVirtual>&& src) noexcept
: HostUpToDate(src.HostUpToDate),
DeviceUpToDate(src.DeviceUpToDate),
DeviceTransferState(std::move(src.DeviceTransferState))
{
}
//--------------------------------------------------------------------
Storage<void, vtkm::cont::StorageTagVirtual>& Storage<void, ::vtkm::cont::StorageTagVirtual>::
operator=(const Storage<void, vtkm::cont::StorageTagVirtual>& src)
{
this->HostUpToDate = src.HostUpToDate;
this->DeviceUpToDate = src.DeviceUpToDate;
this->DeviceTransferState = src.DeviceTransferState;
return *this;
}
//--------------------------------------------------------------------
Storage<void, vtkm::cont::StorageTagVirtual>& Storage<void, ::vtkm::cont::StorageTagVirtual>::
operator=(Storage<void, vtkm::cont::StorageTagVirtual>&& src) noexcept
{
this->HostUpToDate = src.HostUpToDate;
this->DeviceUpToDate = src.DeviceUpToDate;
this->DeviceTransferState = std::move(src.DeviceTransferState);
return *this;
}
//--------------------------------------------------------------------
Storage<void, ::vtkm::cont::StorageTagVirtual>::~Storage()
{
}
//--------------------------------------------------------------------
void Storage<void, ::vtkm::cont::StorageTagVirtual>::ReleaseResourcesExecution()
{
this->DeviceTransferState->releaseDevice();
this->DeviceUpToDate = false;
}
//--------------------------------------------------------------------
void Storage<void, ::vtkm::cont::StorageTagVirtual>::ReleaseResources()
{
this->DeviceTransferState->releaseAll();
this->HostUpToDate = false;
this->DeviceUpToDate = false;
}
//--------------------------------------------------------------------
bool Storage<void, ::vtkm::cont::StorageTagVirtual>::IsSameType(const std::type_info& other) const
{
return typeid(*this) == other;
}
//--------------------------------------------------------------------
std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>>
Storage<void, ::vtkm::cont::StorageTagVirtual>::NewInstance() const
{
return this->MakeNewInstance();
}
//--------------------------------------------------------------------
const vtkm::internal::PortalVirtualBase*
Storage<void, ::vtkm::cont::StorageTagVirtual>::PrepareForInput(
vtkm::cont::DeviceAdapterId devId) const
{
if (devId == vtkm::cont::DeviceAdapterTagUndefined())
{
throw vtkm::cont::ErrorBadValue("device should not be VTKM_DEVICE_ADAPTER_UNDEFINED");
}
if (devId == vtkm::cont::DeviceAdapterTagError())
{
throw vtkm::cont::ErrorBadValue("device should not be VTKM_DEVICE_ADAPTER_ERROR");
}
const bool needsUpload = !(this->DeviceTransferState->valid(devId) && this->DeviceUpToDate);
if (needsUpload)
{ //Either transfer state is pointing to another device, or has
//had the execution resources released. Either way we
//need to re-transfer the execution information
auto* payload = this->DeviceTransferState.get();
this->TransferPortalForInput(*payload, devId);
this->HostUpToDate = false;
this->DeviceUpToDate = true;
}
return this->DeviceTransferState->devicePtr();
}
//--------------------------------------------------------------------
const vtkm::internal::PortalVirtualBase*
Storage<void, ::vtkm::cont::StorageTagVirtual>::PrepareForOutput(vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId)
{
if (devId == vtkm::cont::DeviceAdapterTagUndefined())
{
throw vtkm::cont::ErrorBadValue("device should not be VTKM_DEVICE_ADAPTER_UNDEFINED");
}
if (devId == vtkm::cont::DeviceAdapterTagError())
{
throw vtkm::cont::ErrorBadValue("device should not be VTKM_DEVICE_ADAPTER_ERROR");
}
const bool needsUpload = !(this->DeviceTransferState->valid(devId) && this->DeviceUpToDate);
if (needsUpload)
{
this->TransferPortalForOutput(*(this->DeviceTransferState), numberOfValues, devId);
this->HostUpToDate = false;
this->DeviceUpToDate = true;
}
return this->DeviceTransferState->devicePtr();
}
//--------------------------------------------------------------------
const vtkm::internal::PortalVirtualBase*
Storage<void, ::vtkm::cont::StorageTagVirtual>::GetPortalControl()
{
if (!this->HostUpToDate)
{
//we need to prepare for input and grab the host ptr
auto* payload = this->DeviceTransferState.get();
this->ControlPortalForOutput(*payload);
}
this->DeviceUpToDate = false;
this->HostUpToDate = true;
return this->DeviceTransferState->hostPtr();
}
//--------------------------------------------------------------------
const vtkm::internal::PortalVirtualBase*
Storage<void, ::vtkm::cont::StorageTagVirtual>::GetPortalConstControl() const
{
if (!this->HostUpToDate)
{
//we need to prepare for input and grab the host ptr
vtkm::cont::internal::TransferInfoArray* payload = this->DeviceTransferState.get();
this->ControlPortalForInput(*payload);
}
//We need to mark the device out of date after the conditions
//as they can modify the state of the device
this->DeviceUpToDate = false;
this->HostUpToDate = true;
return this->DeviceTransferState->hostPtr();
}
//--------------------------------------------------------------------
DeviceAdapterId Storage<void, ::vtkm::cont::StorageTagVirtual>::GetDeviceAdapterId() const noexcept
{
return this->DeviceTransferState->deviceId();
}
//--------------------------------------------------------------------
void Storage<void, ::vtkm::cont::StorageTagVirtual>::ControlPortalForOutput(
vtkm::cont::internal::TransferInfoArray&)
{
throw vtkm::cont::ErrorBadValue("StorageTagVirtual by default doesn't support output.");
}
//--------------------------------------------------------------------
void Storage<void, ::vtkm::cont::StorageTagVirtual>::TransferPortalForOutput(
vtkm::cont::internal::TransferInfoArray&,
vtkm::Id,
vtkm::cont::DeviceAdapterId)
{
throw vtkm::cont::ErrorBadValue("StorageTagVirtual by default doesn't support output.");
}
}
}
}

175
vtkm/cont/StorageVirtual.h Normal file

@ -0,0 +1,175 @@
//============================================================================
// 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_h
#define vtk_m_cont_StorageVirtual_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/internal/TransferInfo.h>
#include <vtkm/internal/ArrayPortalVirtual.h>
#include <typeinfo>
namespace vtkm
{
namespace cont
{
struct StorageTagVirtual
{
};
namespace internal
{
template <>
class VTKM_CONT_EXPORT Storage<void, vtkm::cont::StorageTagVirtual>
{
public:
/// \brief construct storage that VTK-m is responsible for
Storage() = default;
Storage(const Storage<void, vtkm::cont::StorageTagVirtual>& src);
Storage(Storage<void, vtkm::cont::StorageTagVirtual>&& src) noexcept;
Storage& operator=(const Storage<void, vtkm::cont::StorageTagVirtual>& src);
Storage& operator=(Storage<void, vtkm::cont::StorageTagVirtual>&& src) noexcept;
virtual ~Storage();
/// Releases any resources being used in the execution environment (that are
/// not being shared by the control environment).
///
/// Only needs to overridden by subclasses such as Zip that have member
/// variables that themselves have execution memory
virtual void ReleaseResourcesExecution();
/// Releases all resources in both the control and execution environments.
///
/// Only needs to overridden by subclasses such as Zip that have member
/// variables that themselves have execution memory
virtual void ReleaseResources();
/// Returns the number of entries in the array.
///
virtual vtkm::Id GetNumberOfValues() const = 0;
/// \brief Allocates an array large enough to hold the given number of values.
///
/// The allocation may be done on an already existing array, but can wipe out
/// any data already in the array. This method can throw
/// ErrorBadAllocation if the array cannot be allocated or
/// ErrorBadValue if the allocation is not feasible (for example, the
/// array storage is read-only).
///
void Allocate(vtkm::Id numberOfValues)
{
std::cout << "StorageVirtual::Allocate(" << numberOfValues << ") Not Implemented!" << std::endl;
} //return this->DoAllocate(numberOfValues); }
/// \brief Reduces the size of the array without changing its values.
///
/// This method allows you to resize the array without reallocating it. The
/// number of entries in the array is changed to \c numberOfValues. The data
/// in the array (from indices 0 to \c numberOfValues - 1) are the same, but
/// \c numberOfValues must be equal or less than the preexisting size
/// (returned from GetNumberOfValues). That is, this method can only be used
/// to shorten the array, not lengthen.
void Shrink(vtkm::Id numberOfValues)
{
std::cout << "StorageVirtual::Shrink(" << numberOfValues << ") Not Implemented!." << std::endl;
} //return this->DoShrink(numberOfValues); }
/// Determines if storage types matches the type passed in.
///
bool IsType(const std::type_info& other) const { return this->IsSameType(other); }
/// \brief Create a new storage of the same type as this storage.
///
/// This method creates a new storage that is the same type as this one and
/// returns a unique_ptr for it. This method is convenient when
/// creating output arrays that should be the same type as some input array.
///
std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>> NewInstance() const;
template <typename DerivedStorage>
const DerivedStorage* Cast() const
{
const DerivedStorage* derived = dynamic_cast<const DerivedStorage*>(this);
if (!derived)
{
VTKM_LOG_CAST_FAIL(*this, DerivedStorage);
throwFailedDynamicCast("StorageVirtual", vtkm::cont::TypeName<DerivedStorage>());
}
VTKM_LOG_CAST_SUCC(*this, derived);
return derived;
}
const vtkm::internal::PortalVirtualBase* PrepareForInput(vtkm::cont::DeviceAdapterId devId) const;
const vtkm::internal::PortalVirtualBase* PrepareForOutput(vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId);
//This needs to cause a host side sync!
//This needs to work before we execute on a device
const vtkm::internal::PortalVirtualBase* GetPortalControl();
//This needs to cause a host side sync!
//This needs to work before we execute on a device
const vtkm::internal::PortalVirtualBase* GetPortalConstControl() const;
/// Returns the DeviceAdapterId for the current device. If there is no device
/// with an up-to-date copy of the data, VTKM_DEVICE_ADAPTER_UNDEFINED is
/// returned.
DeviceAdapterId GetDeviceAdapterId() const noexcept;
private:
//Memory management routines
// virtual void DoAllocate(vtkm::Id numberOfValues) = 0;
// virtual void DoShrink(vtkm::Id numberOfValues) = 0;
//RTTI routines
virtual bool IsSameType(const std::type_info&) const;
virtual std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>> MakeNewInstance()
const = 0;
//Portal routines
virtual void ControlPortalForInput(vtkm::cont::internal::TransferInfoArray& payload) const = 0;
virtual void ControlPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload);
virtual void TransferPortalForInput(vtkm::cont::internal::TransferInfoArray& payload,
vtkm::cont::DeviceAdapterId devId) const = 0;
virtual void TransferPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload,
vtkm::Id numberOfValues,
vtkm::cont::DeviceAdapterId devId);
//These might need to exist in TransferInfoArray
mutable bool HostUpToDate = false;
mutable bool DeviceUpToDate = false;
std::shared_ptr<vtkm::cont::internal::TransferInfoArray> DeviceTransferState =
std::make_shared<vtkm::cont::internal::TransferInfoArray>();
};
} // namespace internal
using StorageVirtual = internal::Storage<void, vtkm::cont::StorageTagVirtual>;
}
} // namespace vtkm::cont
#endif

@ -45,6 +45,7 @@ set(headers
ReverseConnectivityBuilder.h
SimplePolymorphicContainer.h
StorageError.h
TransferInfo.h
VirtualObjectTransfer.h
VirtualObjectTransferShareWithControl.h
)

@ -0,0 +1,68 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/internal/TransferInfo.h>
#include <vtkm/internal/ArrayPortalVirtual.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
bool TransferInfoArray::valid(vtkm::cont::DeviceAdapterId devId) const noexcept
{
return this->DeviceId == devId;
}
void TransferInfoArray::updateHost(
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& host) noexcept
{
this->Host = std::move(host);
}
void TransferInfoArray::updateDevice(vtkm::cont::DeviceAdapterId devId,
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& hostCopy,
const vtkm::internal::PortalVirtualBase* device,
const std::shared_ptr<void>& deviceState) noexcept
{
this->HostCopyOfDevice = std::move(hostCopy);
this->DeviceId = devId;
this->Device = device;
this->DeviceTransferState = deviceState;
}
void TransferInfoArray::releaseDevice()
{
this->DeviceId = vtkm::cont::DeviceAdapterTagUndefined{};
this->Device = nullptr; //The device transfer state own this pointer
this->DeviceTransferState = nullptr; //release the device transfer state
this->HostCopyOfDevice.release(); //we own this pointer so release it
}
void TransferInfoArray::releaseAll()
{
this->Host.release(); //we own this pointer so release it
this->releaseDevice();
}
}
}
}

@ -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_internal_TransferInfo_h
#define vtk_m_cont_internal_TransferInfo_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/Types.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/internal/ArrayPortalVirtual.h>
#include <memory>
namespace vtkm
{
namespace internal
{
class PortalVirtualBase;
}
namespace cont
{
namespace internal
{
struct VTKM_CONT_EXPORT TransferInfoArray
{
bool valid(vtkm::cont::DeviceAdapterId tagValue) const noexcept;
void updateHost(std::unique_ptr<vtkm::internal::PortalVirtualBase>&& host) noexcept;
void updateDevice(
vtkm::cont::DeviceAdapterId id,
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& host_copy, //NOT the same as host version
const vtkm::internal::PortalVirtualBase* device,
const std::shared_ptr<void>& state) noexcept;
void releaseDevice();
void releaseAll();
const vtkm::internal::PortalVirtualBase* hostPtr() const noexcept { return this->Host.get(); }
const vtkm::internal::PortalVirtualBase* devicePtr() const noexcept { return this->Device; }
vtkm::cont::DeviceAdapterId deviceId() const noexcept { return this->DeviceId; }
std::shared_ptr<void>& state() noexcept { return this->DeviceTransferState; }
private:
vtkm::cont::DeviceAdapterId DeviceId = vtkm::cont::DeviceAdapterTagUndefined{};
std::unique_ptr<vtkm::internal::PortalVirtualBase> Host = nullptr;
std::unique_ptr<vtkm::internal::PortalVirtualBase> HostCopyOfDevice = nullptr;
const vtkm::internal::PortalVirtualBase* Device = nullptr;
std::shared_ptr<void> DeviceTransferState = nullptr;
};
}
}
}
#endif

@ -0,0 +1,56 @@
//============================================================================
// 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_internal_ArrayPortalHelpers_h
#define vtk_m_internal_ArrayPortalHelpers_h
#include <vtkm/VecTraits.h>
#include <vtkm/internal/ExportMacros.h>
namespace vtkm
{
namespace internal
{
template <typename PortalType>
struct PortalSupportsGets
{
template <typename U, typename S = decltype(std::declval<U>().Get(vtkm::Id{}))>
static std::true_type has(int);
template <typename U>
static std::false_type has(...);
using type = decltype(has<PortalType>(0));
};
template <typename PortalType>
struct PortalSupportsSets
{
template <typename U,
typename S = decltype(std::declval<U>().Set(vtkm::Id{},
std::declval<typename U::ValueType>()))>
static std::true_type has(int);
template <typename U>
static std::false_type has(...);
using type = decltype(has<PortalType>(0));
};
}
} // namespace vtkm::internal
#endif //vtk_m_internal_ArrayPortalHelpers_h

@ -0,0 +1,144 @@
//============================================================================
// 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_internal_ArrayPortalVirtual_h
#define vtk_m_internal_ArrayPortalVirtual_h
#include <vtkm/VecTraits.h>
#include <vtkm/VirtualObjectBase.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkm/internal/ExportMacros.h>
namespace vtkm
{
namespace internal
{
class VTKM_ALWAYS_EXPORT PortalVirtualBase
{
public:
VTKM_EXEC_CONT PortalVirtualBase() noexcept {}
VTKM_EXEC_CONT virtual ~PortalVirtualBase() noexcept {
//we implement this as we need a destructor with cuda markup.
//Using =default causes cuda free errors inside VirtualObjectTransferCuda
};
};
} // namespace internal
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayPortalVirtual : public internal::PortalVirtualBase
{
public:
using ValueType = T;
//use parents constructor
using PortalVirtualBase::PortalVirtualBase;
VTKM_EXEC_CONT virtual ~ArrayPortalVirtual<T>() = default;
VTKM_EXEC_CONT virtual T Get(vtkm::Id index) const noexcept = 0;
VTKM_EXEC_CONT virtual void Set(vtkm::Id, const T&) const noexcept {}
};
template <typename PortalT>
class VTKM_ALWAYS_EXPORT ArrayPortalWrapper final
: public vtkm::ArrayPortalVirtual<typename PortalT::ValueType>
{
using T = typename PortalT::ValueType;
public:
ArrayPortalWrapper(const PortalT& p) noexcept : ArrayPortalVirtual<T>(), Portal(p) {}
VTKM_EXEC
T Get(vtkm::Id index) const noexcept
{
using call_supported_t = typename internal::PortalSupportsGets<PortalT>::type;
return this->Get(call_supported_t(), index);
}
VTKM_EXEC
void Set(vtkm::Id index, const T& value) const noexcept
{
using call_supported_t = typename internal::PortalSupportsSets<PortalT>::type;
this->Set(call_supported_t(), index, value);
}
private:
// clang-format off
VTKM_EXEC inline T Get(std::true_type, vtkm::Id index) const noexcept { return this->Portal.Get(index); }
VTKM_EXEC inline T Get(std::false_type, vtkm::Id) const noexcept { return T{}; }
VTKM_EXEC inline void Set(std::true_type, vtkm::Id index, const T& value) const noexcept { this->Portal.Set(index, value); }
VTKM_EXEC inline void Set(std::false_type, vtkm::Id, const T&) const noexcept {}
// clang-format on
PortalT Portal;
};
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayPortalRef
{
public:
using ValueType = T;
ArrayPortalRef() noexcept : Portal(nullptr), NumberOfValues(0) {}
ArrayPortalRef(const ArrayPortalVirtual<T>* portal, vtkm::Id numValues) noexcept
: Portal(portal),
NumberOfValues(numValues)
{
}
//Currently this needs to be valid on both the host and device for cuda, so we can't
//call the underlying portal as that uses device virtuals and the method will fail.
//We need to seriously look at the interaction of portals and iterators for device
//adapters and determine a better approach as iterators<Portal> are really fat
VTKM_EXEC_CONT inline vtkm::Id GetNumberOfValues() const noexcept { return this->NumberOfValues; }
//This isn't valid on the host for cuda
VTKM_EXEC_CONT inline T Get(vtkm::Id index) const noexcept { return this->Portal->Get(index); }
//This isn't valid on the host for
VTKM_EXEC_CONT inline void Set(vtkm::Id index, const T& t) const noexcept
{
this->Portal->Set(index, t);
}
const ArrayPortalVirtual<T>* Portal;
vtkm::Id NumberOfValues;
};
template <typename T>
inline ArrayPortalRef<T> make_ArrayPortalRef(const ArrayPortalVirtual<T>* portal,
vtkm::Id numValues) noexcept
{
return ArrayPortalRef<T>(portal, numValues);
}
} // namespace vtkm
#endif

@ -56,8 +56,10 @@ unset(VTKM_NO_ASSERT)
set(headers
ArrayPortalHelpers.h
ArrayPortalUniformPointCoordinates.h
ArrayPortalValueReference.h
ArrayPortalVirtual.h
Assume.h
brigand.hpp
ConfigureFor32.h