2018-11-06 16:20:30 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2018-11-06 16:20:30 +00:00
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_cont_StorageVirtual_h
|
|
|
|
#define vtk_m_cont_StorageVirtual_h
|
|
|
|
|
|
|
|
#include <vtkm/cont/vtkm_cont_export.h>
|
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
2018-11-06 16:20:30 +00:00
|
|
|
#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
|
|
|
|
{
|
|
|
|
|
2020-03-09 21:53:38 +00:00
|
|
|
// A control-side version of ArrayPortalRef that also manages the object created.
|
|
|
|
template <typename T>
|
|
|
|
class VTKM_ALWAYS_EXPORT ArrayPortalRef : public vtkm::ArrayPortalRef<T>
|
|
|
|
{
|
|
|
|
std::shared_ptr<vtkm::ArrayPortalVirtual<T>> ManagedPortal;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ArrayPortalRef() = default;
|
|
|
|
|
|
|
|
ArrayPortalRef(std::shared_ptr<vtkm::ArrayPortalVirtual<T>> portal, vtkm::Id numValues) noexcept
|
2020-08-17 14:18:24 +00:00
|
|
|
: vtkm::ArrayPortalRef<T>(portal.get(), numValues)
|
|
|
|
, ManagedPortal(portal)
|
2020-03-09 21:53:38 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace cont
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline vtkm::cont::ArrayPortalRef<T> make_ArrayPortalRef(
|
|
|
|
std::shared_ptr<vtkm::ArrayPortalVirtual<T>> portal,
|
|
|
|
vtkm::Id numValues)
|
|
|
|
{
|
|
|
|
return vtkm::cont::ArrayPortalRef<T>(portal, numValues);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace vtkm
|
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
|
|
|
|
2018-12-18 20:10:55 +00:00
|
|
|
struct VTKM_ALWAYS_EXPORT StorageTagVirtual
|
2018-11-06 16:20:30 +00:00
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
|
|
|
|
class VTKM_CONT_EXPORT StorageVirtual
|
2018-11-06 16:20:30 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
/// \brief construct storage that VTK-m is responsible for
|
2019-02-10 08:46:43 +00:00
|
|
|
StorageVirtual() = default;
|
|
|
|
StorageVirtual(const StorageVirtual& src);
|
|
|
|
StorageVirtual(StorageVirtual&& src) noexcept;
|
|
|
|
StorageVirtual& operator=(const StorageVirtual& src);
|
|
|
|
StorageVirtual& operator=(StorageVirtual&& src) noexcept;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
virtual ~StorageVirtual();
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// 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
|
2019-02-25 18:31:52 +00:00
|
|
|
virtual void ReleaseResourcesExecution() = 0;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// 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
|
2019-02-25 18:31:52 +00:00
|
|
|
virtual void ReleaseResources() = 0;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// 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).
|
|
|
|
///
|
2019-02-25 18:31:52 +00:00
|
|
|
virtual void Allocate(vtkm::Id numberOfValues) = 0;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// \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.
|
2019-02-25 18:31:52 +00:00
|
|
|
virtual void Shrink(vtkm::Id numberOfValues) = 0;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// Determines if storage types matches the type passed in.
|
|
|
|
///
|
2018-12-18 20:10:55 +00:00
|
|
|
template <typename DerivedStorage>
|
|
|
|
bool IsType() const
|
|
|
|
{ //needs optimizations based on platform. !OSX can use typeid
|
|
|
|
return nullptr != dynamic_cast<const DerivedStorage*>(this);
|
|
|
|
}
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// \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.
|
|
|
|
///
|
2019-02-10 08:46:43 +00:00
|
|
|
std::unique_ptr<StorageVirtual> NewInstance() const;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
template <typename DerivedStorage>
|
|
|
|
const DerivedStorage* Cast() const
|
|
|
|
{
|
|
|
|
const DerivedStorage* derived = dynamic_cast<const DerivedStorage*>(this);
|
|
|
|
if (!derived)
|
|
|
|
{
|
|
|
|
VTKM_LOG_CAST_FAIL(*this, DerivedStorage);
|
2019-02-28 18:15:27 +00:00
|
|
|
throwFailedDynamicCast("StorageVirtual", vtkm::cont::TypeToString<DerivedStorage>());
|
2018-11-06 16:20:30 +00:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
2018-11-28 15:36:45 +00:00
|
|
|
const vtkm::internal::PortalVirtualBase* PrepareForInPlace(vtkm::cont::DeviceAdapterId devId);
|
|
|
|
|
2018-11-06 16:20:30 +00:00
|
|
|
//This needs to cause a host side sync!
|
|
|
|
//This needs to work before we execute on a device
|
2020-03-09 21:53:38 +00:00
|
|
|
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& WritePortal();
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
//This needs to cause a host side sync!
|
|
|
|
//This needs to work before we execute on a device
|
2020-03-09 21:53:38 +00:00
|
|
|
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& ReadPortal() const;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
/// 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;
|
|
|
|
|
2018-11-28 15:36:45 +00:00
|
|
|
|
|
|
|
enum struct OutputMode
|
|
|
|
{
|
|
|
|
WRITE,
|
|
|
|
READ_WRITE
|
|
|
|
};
|
|
|
|
|
2019-02-25 18:31:52 +00:00
|
|
|
protected:
|
|
|
|
/// Drop the reference to the execution portal. The underlying array handle might still be
|
|
|
|
/// managing data on the execution side, but our references might be out of date, so drop
|
|
|
|
/// them and refresh them later if necessary.
|
|
|
|
void DropExecutionPortal();
|
|
|
|
|
|
|
|
/// Drop the reference to all portals. The underlying array handle might still be managing data,
|
|
|
|
/// but our references might be out of date, so drop them and refresh them later if necessary.
|
|
|
|
void DropAllPortals();
|
|
|
|
|
2018-11-06 16:20:30 +00:00
|
|
|
private:
|
|
|
|
//Memory management routines
|
|
|
|
// virtual void DoAllocate(vtkm::Id numberOfValues) = 0;
|
|
|
|
// virtual void DoShrink(vtkm::Id numberOfValues) = 0;
|
|
|
|
|
|
|
|
//RTTI routines
|
2019-02-10 08:46:43 +00:00
|
|
|
virtual std::unique_ptr<StorageVirtual> MakeNewInstance() const = 0;
|
2018-11-06 16:20:30 +00:00
|
|
|
|
|
|
|
//Portal routines
|
|
|
|
virtual void ControlPortalForInput(vtkm::cont::internal::TransferInfoArray& payload) const = 0;
|
|
|
|
virtual void ControlPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload);
|
2018-11-28 15:36:45 +00:00
|
|
|
|
|
|
|
|
2018-11-06 16:20:30 +00:00
|
|
|
virtual void TransferPortalForInput(vtkm::cont::internal::TransferInfoArray& payload,
|
|
|
|
vtkm::cont::DeviceAdapterId devId) const = 0;
|
|
|
|
virtual void TransferPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload,
|
2018-11-28 15:36:45 +00:00
|
|
|
OutputMode mode,
|
2018-11-06 16:20:30 +00:00
|
|
|
vtkm::Id numberOfValues,
|
|
|
|
vtkm::cont::DeviceAdapterId devId);
|
|
|
|
|
2020-03-09 21:53:38 +00:00
|
|
|
//This might need to exist in TransferInfoArray
|
2018-11-06 16:20:30 +00:00
|
|
|
mutable bool DeviceUpToDate = false;
|
|
|
|
std::shared_ptr<vtkm::cont::internal::TransferInfoArray> DeviceTransferState =
|
|
|
|
std::make_shared<vtkm::cont::internal::TransferInfoArray>();
|
|
|
|
};
|
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
template <typename T, typename S>
|
|
|
|
class VTKM_ALWAYS_EXPORT StorageVirtualImpl final
|
|
|
|
: public vtkm::cont::internal::detail::StorageVirtual
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VTKM_CONT
|
|
|
|
explicit StorageVirtualImpl(const vtkm::cont::ArrayHandle<T, S>& ah);
|
|
|
|
|
|
|
|
explicit StorageVirtualImpl(vtkm::cont::ArrayHandle<T, S>&& ah) noexcept;
|
|
|
|
|
|
|
|
VTKM_CONT
|
2020-01-13 15:06:47 +00:00
|
|
|
~StorageVirtualImpl() override = default;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
const vtkm::cont::ArrayHandle<T, S>& GetHandle() const { return this->Handle; }
|
|
|
|
|
2019-02-25 18:31:52 +00:00
|
|
|
vtkm::Id GetNumberOfValues() const override { return this->Handle.GetNumberOfValues(); }
|
|
|
|
|
|
|
|
void ReleaseResourcesExecution() override;
|
|
|
|
void ReleaseResources() override;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
2019-02-25 18:31:52 +00:00
|
|
|
void Allocate(vtkm::Id numberOfValues) override;
|
|
|
|
void Shrink(vtkm::Id numberOfValues) override;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
private:
|
2019-02-25 21:06:19 +00:00
|
|
|
std::unique_ptr<vtkm::cont::internal::detail::StorageVirtual> MakeNewInstance() const override
|
2019-02-10 08:46:43 +00:00
|
|
|
{
|
|
|
|
return std::unique_ptr<vtkm::cont::internal::detail::StorageVirtual>(
|
|
|
|
new StorageVirtualImpl<T, S>{ vtkm::cont::ArrayHandle<T, S>{} });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-25 21:06:19 +00:00
|
|
|
void ControlPortalForInput(vtkm::cont::internal::TransferInfoArray& payload) const override;
|
|
|
|
void ControlPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload) override;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
void TransferPortalForInput(vtkm::cont::internal::TransferInfoArray& payload,
|
2019-02-25 21:06:19 +00:00
|
|
|
vtkm::cont::DeviceAdapterId devId) const override;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
void TransferPortalForOutput(vtkm::cont::internal::TransferInfoArray& payload,
|
|
|
|
OutputMode mode,
|
|
|
|
vtkm::Id numberOfValues,
|
2019-02-25 21:06:19 +00:00
|
|
|
vtkm::cont::DeviceAdapterId devId) override;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
vtkm::cont::ArrayHandle<T, S> Handle;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
template <typename T>
|
2019-02-26 19:23:18 +00:00
|
|
|
class VTKM_ALWAYS_EXPORT Storage<T, vtkm::cont::StorageTagVirtual>
|
2019-02-10 08:46:43 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
using ValueType = T;
|
|
|
|
|
2020-03-09 21:53:38 +00:00
|
|
|
using PortalType = vtkm::cont::ArrayPortalRef<T>;
|
|
|
|
using PortalConstType = vtkm::cont::ArrayPortalRef<T>;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
Storage() = default;
|
|
|
|
|
2019-02-26 19:23:18 +00:00
|
|
|
// Should never really be used, but just in case.
|
|
|
|
Storage(const Storage<T, vtkm::cont::StorageTagVirtual>&) = default;
|
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
template <typename S>
|
|
|
|
Storage(const vtkm::cont::ArrayHandle<T, S>& srcArray)
|
|
|
|
: VirtualStorage(std::make_shared<detail::StorageVirtualImpl<T, S>>(srcArray))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
~Storage() = default;
|
|
|
|
|
|
|
|
PortalType GetPortal()
|
|
|
|
{
|
|
|
|
return make_ArrayPortalRef(
|
2020-03-09 21:53:38 +00:00
|
|
|
std::shared_ptr<vtkm::ArrayPortalVirtual<T>>(reinterpret_cast<vtkm::ArrayPortalVirtual<T>*>(
|
|
|
|
this->VirtualStorage->WritePortal().release())),
|
2019-02-10 08:46:43 +00:00
|
|
|
this->GetNumberOfValues());
|
|
|
|
}
|
2018-11-06 16:20:30 +00:00
|
|
|
|
2019-02-10 08:46:43 +00:00
|
|
|
PortalConstType GetPortalConst() const
|
|
|
|
{
|
2020-01-28 19:14:32 +00:00
|
|
|
return make_ArrayPortalRef(
|
2020-03-09 21:53:38 +00:00
|
|
|
std::shared_ptr<vtkm::ArrayPortalVirtual<T>>(reinterpret_cast<vtkm::ArrayPortalVirtual<T>*>(
|
|
|
|
this->VirtualStorage->ReadPortal().release())),
|
2020-01-28 19:14:32 +00:00
|
|
|
this->GetNumberOfValues());
|
2019-02-10 08:46:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vtkm::Id GetNumberOfValues() const { return this->VirtualStorage->GetNumberOfValues(); }
|
|
|
|
|
2019-02-25 19:43:16 +00:00
|
|
|
void Allocate(vtkm::Id numberOfValues);
|
2019-02-10 08:46:43 +00:00
|
|
|
|
2019-02-25 19:43:16 +00:00
|
|
|
void Shrink(vtkm::Id numberOfValues);
|
2019-02-10 08:46:43 +00:00
|
|
|
|
2019-02-25 19:43:16 +00:00
|
|
|
void ReleaseResources();
|
2019-02-10 08:46:43 +00:00
|
|
|
|
2019-02-25 19:43:16 +00:00
|
|
|
Storage<T, vtkm::cont::StorageTagVirtual> NewInstance() const;
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
const detail::StorageVirtual* GetStorageVirtual() const { return this->VirtualStorage.get(); }
|
2019-02-26 19:23:18 +00:00
|
|
|
detail::StorageVirtual* GetStorageVirtual() { return this->VirtualStorage.get(); }
|
2019-02-10 08:46:43 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::shared_ptr<detail::StorageVirtual> VirtualStorage;
|
|
|
|
|
|
|
|
Storage(std::shared_ptr<detail::StorageVirtual> virtualStorage)
|
|
|
|
: VirtualStorage(virtualStorage)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace internal
|
2018-11-06 16:20:30 +00:00
|
|
|
}
|
|
|
|
} // namespace vtkm::cont
|
|
|
|
|
2019-02-26 19:23:18 +00:00
|
|
|
#ifndef vtk_m_cont_StorageVirtual_hxx
|
2019-02-10 08:46:43 +00:00
|
|
|
#include <vtkm/cont/StorageVirtual.hxx>
|
2019-02-26 19:23:18 +00:00
|
|
|
#endif
|
2019-02-10 08:46:43 +00:00
|
|
|
|
2018-11-06 16:20:30 +00:00
|
|
|
#endif
|