mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Add standard support for read-only storage
Many of the fancy `ArrayHandle`s are read-only and therefore connot really create write portals. Likewise, many `ArrayHandle`s (both read- only and read/write) have no way to resize themselves. In this case, implementing the `CreateWritePortal` and `ResizeBuffers` methods in the `Storage` class was troublesome. Mostly they just threw an exception, but they also sometimes had to deal with cases where the behavior was allowed. To simplify code for developers, this introduces a pair of macros: `VTKM_STORAGE_NO_RESIZE` and `VTKM_STORAGE_NO_WRITE_PORTAL`. These can be declared in a `Storage` implementation when the storage has no viable way to resize itself and create a write portal, respectively. Having boilerplate code for these methods also helps work around expected behavior for `ResizeBuffers`. `ResizeBuffers` should silently work when resizing to the same size. Also `ResizeBuffers` should behave well when resizing to 0 as that is what `ReleaseResources` does.
This commit is contained in:
parent
a6b9d5c497
commit
7811cc4b1e
@ -221,6 +221,8 @@ class Storage<vtkm::Vec<T, 3>, vtkm::cont::StorageTagCartesianProduct<ST1, ST2,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
VTKM_STORAGE_NO_RESIZE;
|
||||||
|
|
||||||
using ReadPortalType =
|
using ReadPortalType =
|
||||||
vtkm::internal::ArrayPortalCartesianProduct<vtkm::Vec<T, 3>,
|
vtkm::internal::ArrayPortalCartesianProduct<vtkm::Vec<T, 3>,
|
||||||
typename Storage1::ReadPortalType,
|
typename Storage1::ReadPortalType,
|
||||||
@ -245,22 +247,6 @@ public:
|
|||||||
Storage3::GetNumberOfValues(Buffers3(buffers)));
|
Storage3::GetNumberOfValues(Buffers3(buffers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
|
|
||||||
vtkm::cont::internal::Buffer* buffers,
|
|
||||||
vtkm::CopyFlag vtkmNotUsed(preserve),
|
|
||||||
vtkm::cont::Token& vtkmNotUsed(token))
|
|
||||||
{
|
|
||||||
if (numValues == GetNumberOfValues(buffers))
|
|
||||||
{
|
|
||||||
// In general, we don't allow resizing of the array, but if it was "allocated" to the
|
|
||||||
// correct size, we will allow that.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadAllocation("Does not make sense.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::cont::DeviceAdapterId device,
|
vtkm::cont::DeviceAdapterId device,
|
||||||
vtkm::cont::Token& token)
|
vtkm::cont::Token& token)
|
||||||
|
@ -97,11 +97,10 @@ struct VTKM_ALWAYS_EXPORT
|
|||||||
{
|
{
|
||||||
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
|
VTKM_IS_TRIVIALLY_COPYABLE(ArrayPortalType);
|
||||||
|
|
||||||
using ReadPortalType = ArrayPortalType;
|
VTKM_STORAGE_NO_RESIZE;
|
||||||
|
VTKM_STORAGE_NO_WRITE_PORTAL;
|
||||||
|
|
||||||
// Note that this portal is almost certainly read-only, so you will probably get
|
using ReadPortalType = ArrayPortalType;
|
||||||
// an error if you try to write to it.
|
|
||||||
using WritePortalType = ArrayPortalType;
|
|
||||||
|
|
||||||
// Implicit array has one buffer that should be empty (NumberOfBytes = 0), but holds
|
// Implicit array has one buffer that should be empty (NumberOfBytes = 0), but holds
|
||||||
// the metadata for the array.
|
// the metadata for the array.
|
||||||
@ -112,35 +111,12 @@ struct VTKM_ALWAYS_EXPORT
|
|||||||
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
|
return buffers[0].GetMetaData<ArrayPortalType>().GetNumberOfValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
|
|
||||||
vtkm::cont::internal::Buffer* buffers,
|
|
||||||
vtkm::CopyFlag,
|
|
||||||
vtkm::cont::Token&)
|
|
||||||
{
|
|
||||||
if (numValues == GetNumberOfValues(buffers))
|
|
||||||
{
|
|
||||||
// In general, we don't allow resizing of the array, but if it was "allocated" to the
|
|
||||||
// correct size, we will allow that.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadAllocation("Cannot allocate/resize implicit arrays.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::cont::DeviceAdapterId,
|
vtkm::cont::DeviceAdapterId,
|
||||||
vtkm::cont::Token&)
|
vtkm::cont::Token&)
|
||||||
{
|
{
|
||||||
return buffers[0].GetMetaData<ArrayPortalType>();
|
return buffers[0].GetMetaData<ArrayPortalType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer*,
|
|
||||||
vtkm::cont::DeviceAdapterId,
|
|
||||||
vtkm::cont::Token&)
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadAllocation("Cannot write to implicit arrays.");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Given an array portal, returns the buffers for the `ArrayHandle` with a storage that
|
/// Given an array portal, returns the buffers for the `ArrayHandle` with a storage that
|
||||||
|
@ -252,16 +252,14 @@ class Storage<typename StorageTagTransform<ArrayHandleType, FunctorType>::ValueT
|
|||||||
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 1;
|
static constexpr vtkm::IdComponent NUM_METADATA_BUFFERS = 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
VTKM_STORAGE_NO_RESIZE;
|
||||||
|
VTKM_STORAGE_NO_WRITE_PORTAL;
|
||||||
|
|
||||||
using ReadPortalType =
|
using ReadPortalType =
|
||||||
vtkm::internal::ArrayPortalTransform<ValueType,
|
vtkm::internal::ArrayPortalTransform<ValueType,
|
||||||
typename ArrayHandleType::ReadPortalType,
|
typename ArrayHandleType::ReadPortalType,
|
||||||
typename FunctorManager::FunctorType>;
|
typename FunctorManager::FunctorType>;
|
||||||
|
|
||||||
// Note that this array is read only, so you really should only be getting the const
|
|
||||||
// version of the portal. If you actually try to write to this portal, you will
|
|
||||||
// get an error.
|
|
||||||
using WritePortalType = ReadPortalType;
|
|
||||||
|
|
||||||
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers()
|
VTKM_CONT static vtkm::IdComponent GetNumberOfBuffers()
|
||||||
{
|
{
|
||||||
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS;
|
return SourceStorage::GetNumberOfBuffers() + NUM_METADATA_BUFFERS;
|
||||||
@ -272,23 +270,6 @@ public:
|
|||||||
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS);
|
return SourceStorage::GetNumberOfValues(buffers + NUM_METADATA_BUFFERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
|
|
||||||
vtkm::cont::internal::Buffer* buffers,
|
|
||||||
vtkm::CopyFlag vtkmNotUsed(preserve),
|
|
||||||
vtkm::cont::Token& vtkmNotUsed(token))
|
|
||||||
{
|
|
||||||
if (numValues == GetNumberOfValues(buffers))
|
|
||||||
{
|
|
||||||
// In general, we don't allow resizing of the array, but if it was "allocated" to the
|
|
||||||
// correct size, we will allow that.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadAllocation(
|
|
||||||
"ArrayHandleTransform is read only. It cannot be allocated.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::cont::DeviceAdapterId device,
|
vtkm::cont::DeviceAdapterId device,
|
||||||
vtkm::cont::Token& token)
|
vtkm::cont::Token& token)
|
||||||
@ -307,14 +288,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer*,
|
|
||||||
vtkm::cont::DeviceAdapterId,
|
|
||||||
vtkm::cont::Token&)
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadType(
|
|
||||||
"ArrayHandleTransform is read only. Cannot get writable portal.");
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
|
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers(
|
||||||
const ArrayHandleType& handle,
|
const ArrayHandleType& handle,
|
||||||
const FunctorType& functor = FunctorType())
|
const FunctorType& functor = FunctorType())
|
||||||
|
@ -151,6 +151,7 @@ set(sources
|
|||||||
Initialize.cxx
|
Initialize.cxx
|
||||||
Logging.cxx
|
Logging.cxx
|
||||||
RuntimeDeviceTracker.cxx
|
RuntimeDeviceTracker.cxx
|
||||||
|
Storage.cxx
|
||||||
Token.cxx
|
Token.cxx
|
||||||
TryExecute.cxx
|
TryExecute.cxx
|
||||||
)
|
)
|
||||||
|
45
vtkm/cont/Storage.cxx
Normal file
45
vtkm/cont/Storage.cxx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//============================================================================
|
||||||
|
// Copyright (c) Kitware, Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
// See LICENSE.txt for details.
|
||||||
|
//
|
||||||
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include <vtkm/cont/Storage.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
void StorageNoResizeImpl(vtkm::Id currentNumValues,
|
||||||
|
vtkm::Id requestedNumValues,
|
||||||
|
std::string storageTagName)
|
||||||
|
{
|
||||||
|
if (currentNumValues == requestedNumValues)
|
||||||
|
{
|
||||||
|
// Array resized to current size. This is OK.
|
||||||
|
}
|
||||||
|
else if (requestedNumValues == 0)
|
||||||
|
{
|
||||||
|
// Array resized to zero. This can happen when releasing resources.
|
||||||
|
// Should we try to clear out the buffers, or avoid that for messing up shared buffers?
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadAllocation("Cannot resize arrays with storage type of " +
|
||||||
|
storageTagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont::internal::detail
|
@ -18,10 +18,16 @@
|
|||||||
#define VTKM_STORAGE VTKM_STORAGE_BASIC
|
#define VTKM_STORAGE VTKM_STORAGE_BASIC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <vtkm/Flags.h>
|
||||||
#include <vtkm/StaticAssert.h>
|
#include <vtkm/StaticAssert.h>
|
||||||
|
|
||||||
#include <vtkm/cont/vtkm_cont_export.h>
|
#include <vtkm/internal/ArrayPortalDummy.h>
|
||||||
#include <vtkm/internal/ExportMacros.h>
|
|
||||||
|
#include <vtkm/cont/ErrorBadAllocation.h>
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
#include <vtkm/cont/Token.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/internal/Buffer.h>
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
@ -173,6 +179,48 @@ public:
|
|||||||
};
|
};
|
||||||
#endif // VTKM_DOXYGEN_ONLY
|
#endif // VTKM_DOXYGEN_ONLY
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKM_CONT_EXPORT void StorageNoResizeImpl(vtkm::Id currentNumValues,
|
||||||
|
vtkm::Id requestedNumValues,
|
||||||
|
std::string storageTagName);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename StorageType>
|
||||||
|
struct StorageTraits;
|
||||||
|
|
||||||
|
template <typename T, typename S>
|
||||||
|
struct StorageTraits<vtkm::cont::internal::Storage<T, S>>
|
||||||
|
{
|
||||||
|
using ValueType = T;
|
||||||
|
using Tag = S;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VTKM_STORAGE_NO_RESIZE \
|
||||||
|
VTKM_CONT static void ResizeBuffers( \
|
||||||
|
vtkm::Id numValues, vtkm::cont::internal::Buffer* buffers, vtkm::CopyFlag, vtkm::cont::Token&) \
|
||||||
|
{ \
|
||||||
|
vtkm::cont::internal::detail::StorageNoResizeImpl( \
|
||||||
|
GetNumberOfValues(buffers), \
|
||||||
|
numValues, \
|
||||||
|
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
|
||||||
|
} \
|
||||||
|
using ResizeBuffersEatComma = void
|
||||||
|
|
||||||
|
#define VTKM_STORAGE_NO_WRITE_PORTAL \
|
||||||
|
using WritePortalType = vtkm::internal::ArrayPortalDummy< \
|
||||||
|
typename vtkm::cont::internal::StorageTraits<Storage>::ValueType>; \
|
||||||
|
VTKM_CONT static WritePortalType CreateWritePortal( \
|
||||||
|
vtkm::cont::internal::Buffer*, vtkm::cont::DeviceAdapterId, vtkm::cont::Token&) \
|
||||||
|
{ \
|
||||||
|
throw vtkm::cont::ErrorBadAllocation( \
|
||||||
|
"Cannot write to arrays with storage type of " + \
|
||||||
|
vtkm::cont::TypeToString<typename vtkm::cont::internal::StorageTraits<Storage>::Tag>()); \
|
||||||
|
} \
|
||||||
|
using CreateWritePortalEatComma = void
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
}
|
}
|
||||||
} // namespace vtkm::cont
|
} // namespace vtkm::cont
|
||||||
|
@ -343,8 +343,6 @@ private:
|
|||||||
vtkm::cont::ArrayCopy(soaArray, basicArray);
|
vtkm::cont::ArrayCopy(soaArray, basicArray);
|
||||||
VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE);
|
VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE);
|
||||||
CheckPortal(basicArray.ReadPortal());
|
CheckPortal(basicArray.ReadPortal());
|
||||||
|
|
||||||
soaArray.ReleaseResources();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -373,6 +371,9 @@ private:
|
|||||||
vtkm::cont::make_ArrayHandleSOA(vtkm::CopyFlag::Off, vector0, vector1, vector2);
|
vtkm::cont::make_ArrayHandleSOA(vtkm::CopyFlag::Off, vector0, vector1, vector2);
|
||||||
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
|
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
|
||||||
CheckPortal(soaArray.ReadPortal());
|
CheckPortal(soaArray.ReadPortal());
|
||||||
|
|
||||||
|
// Make sure calling ReleaseResources does not result in error.
|
||||||
|
soaArray.ReleaseResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
41
vtkm/internal/ArrayPortalDummy.h
Normal file
41
vtkm/internal/ArrayPortalDummy.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//============================================================================
|
||||||
|
// Copyright (c) Kitware, Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
// See LICENSE.txt for details.
|
||||||
|
//
|
||||||
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
|
//============================================================================
|
||||||
|
#ifndef vtk_m_internal_ArrayPortalDummy
|
||||||
|
#define vtk_m_internal_ArrayPortalDummy
|
||||||
|
|
||||||
|
#include <vtkm/Assert.h>
|
||||||
|
#include <vtkm/Types.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
/// A class that can be used in place of an `ArrayPortal` when the `ArrayPortal` is
|
||||||
|
/// not actually supported. It allows templates to be compiled, but will cause undefined
|
||||||
|
/// behavior if actually used.
|
||||||
|
template <typename T>
|
||||||
|
struct ArrayPortalDummy
|
||||||
|
{
|
||||||
|
using ValueType = T;
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return 0; }
|
||||||
|
|
||||||
|
VTKM_EXEC_CONT ValueType Get(vtkm::Id) const
|
||||||
|
{
|
||||||
|
VTKM_ASSERT(false && "Tried to use a dummy portal.");
|
||||||
|
return ValueType{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace vtkm::internal
|
||||||
|
|
||||||
|
#endif //vtk_m_internal_ArrayPortalDummy
|
@ -49,6 +49,7 @@ vtkm_install_headers(vtkm/internal
|
|||||||
|
|
||||||
set(headers
|
set(headers
|
||||||
ArrayPortalBasic.h
|
ArrayPortalBasic.h
|
||||||
|
ArrayPortalDummy.h
|
||||||
ArrayPortalHelpers.h
|
ArrayPortalHelpers.h
|
||||||
ArrayPortalUniformPointCoordinates.h
|
ArrayPortalUniformPointCoordinates.h
|
||||||
ArrayPortalValueReference.h
|
ArrayPortalValueReference.h
|
||||||
|
Loading…
Reference in New Issue
Block a user