Commit 6e1cbaa1 authored by Robert Maynard's avatar Robert Maynard

Add StorageVirtual and ArrayHandleVirtual to vtkm::cont

parent 20d02fde
......@@ -58,6 +58,7 @@ set(headers
VecAxisAlignedPointCoordinates.h
VecFromPortal.h
VecFromPortalPermute.h
VecFromVirtPortal.h
VectorAnalysis.h
VecTraits.h
VecVariable.h
......
//============================================================================
// 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
//============================================================================
// 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
//============================================================================
// 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
)
......
//============================================================================
// 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
......
//============================================================================
// 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.");
}
}
}
}
//============================================================================
// 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
{