Add UnknownArrayHandle::ExtractArrayFromComponents
This method allows you to extract an `ArrayHandle` from `UnknownArrayHandle` when you only know the base component type. Also removed the `Read/WritePortalForBaseComponentType` method from `UnknownArrayHandle`. This functionality is subsumed by `ExtractArrayFromComponents`.
This commit is contained in:
parent
755af739e3
commit
7dd9b4252a
@ -16,11 +16,10 @@
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
#include <vtkm/cont/ArrayHandleRecombineVec.h>
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/DefaultTypes.h>
|
||||
|
||||
#include <vtkm/cont/internal/ArrayPortalFromExtractedComponents.h>
|
||||
|
||||
#include <memory>
|
||||
#include <typeindex>
|
||||
|
||||
@ -553,52 +552,56 @@ public:
|
||||
return ComponentArrayType(buffers);
|
||||
}
|
||||
|
||||
///@{
|
||||
/// \brief Convenience portal to access all components (in control environment).
|
||||
/// \brief Extract the array knowing only the component type of the array.
|
||||
///
|
||||
/// This method returns a portal that allows you to access all the values in the contained
|
||||
/// portal by knowing only the type of the base component. The `BaseComponentType` has to
|
||||
/// be specified and must match the contained array (i.e.the result of `IsBaseComponentType`
|
||||
/// must succeed for the given type).
|
||||
/// This method returns an `ArrayHandle` that points to the data in the array. This method
|
||||
/// differs from `AsArrayHandle` because you do not need to know the exact `ValueType` and
|
||||
/// `StorageTag` of the array. Instead, you only need to know the base component type.
|
||||
///
|
||||
/// Note that the returned portal is not thread safe, but you may safely create multiple portals
|
||||
/// for multiple threads.
|
||||
/// `ExtractArrayFromComponents` works by calling the `ExtractComponent` method and then
|
||||
/// combining them together in a fancy `ArrayHandle`. This allows you to ignore the storage
|
||||
/// type of the underlying array as well as any `Vec` structure of the value type. However,
|
||||
/// it also places some limitations on how the data can be pulled from the data.
|
||||
///
|
||||
/// First, you have to specify the base component type. This must match the data in the
|
||||
/// underlying array (as reported by `IsBaseComponentType`).
|
||||
///
|
||||
/// Second, the array returned will have the `Vec`s flattened. For example, if the underlying
|
||||
/// array has a `ValueType` of `Vec<Vec<T, 3>, 3>`, then this method will tread the data as
|
||||
/// if it was `Vec<T, 9>`. There is no way to get an array with `Vec` of `Vec` values.
|
||||
///
|
||||
/// Third, because the `Vec` length of the values in the returned `ArrayHandle` must be
|
||||
/// determined at runtime, that can break many assumptions of using `Vec` objects. The
|
||||
/// type is not going to be a `Vec<T,N>` type but rather an internal class that is intended
|
||||
/// to behave like that. The type should behave mostly like a `Vec`, but will have some
|
||||
/// differences that can lead to unexpected behavior. For example, this `Vec`-like object
|
||||
/// will not have a `NUM_COMPONENTS` constant static expression because it is not known
|
||||
/// at compile time. (Use the `GetNumberOfComponents` method instead.) And for the same
|
||||
/// reason you will not be able to pass these objects to classes overloaded or templated
|
||||
/// on the `Vec` type. Also, these `Vec`-like objects cannot be created as new instances.
|
||||
/// Thus, you will likely have to iterate over all components rather than do operations on
|
||||
/// the whole `Vec`.
|
||||
///
|
||||
/// Fourth, because `ExtractArrayFromComponents` uses `ExtractComponent` to pull data from
|
||||
/// the array (which in turn uses `ArrayExtractComponent`), there are some `ArrayHandle` types
|
||||
/// that will require copying data to a new array. This could be problematic in cases where
|
||||
/// you want to write to the array. To prevent data from being copied, set the optional
|
||||
/// `allowCopy` to `vtkm::CopyFlag::Off`. This will cause an exception to be thrown if
|
||||
/// the resulting array cannot reference the memory held in this `UnknownArrayHandle`.
|
||||
///
|
||||
template <typename BaseComponentType>
|
||||
VTKM_CONT vtkm::cont::internal::ArrayPortalFromExtractedComponents<
|
||||
typename vtkm::cont::ArrayHandleStride<BaseComponentType>::ReadPortalType>
|
||||
ReadPortalForBaseComponentType() const
|
||||
VTKM_CONT vtkm::cont::ArrayHandleRecombineVec<BaseComponentType> ExtractArrayFromComponents(
|
||||
vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On) const
|
||||
{
|
||||
vtkm::cont::ArrayHandleRecombineVec<BaseComponentType> result;
|
||||
vtkm::IdComponent numComponents = this->GetNumberOfComponentsFlat();
|
||||
vtkm::cont::internal::ArrayPortalFromExtractedComponents<
|
||||
typename vtkm::cont::ArrayHandleStride<BaseComponentType>::ReadPortalType>
|
||||
portal(numComponents);
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex)
|
||||
{
|
||||
auto array = this->ExtractComponent<BaseComponentType>(cIndex, vtkm::CopyFlag::On);
|
||||
portal.AddArray(array, array.ReadPortal());
|
||||
result.AppendComponentArray(this->ExtractComponent<BaseComponentType>(cIndex, allowCopy));
|
||||
}
|
||||
return portal;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename BaseComponentType>
|
||||
VTKM_CONT vtkm::cont::internal::ArrayPortalFromExtractedComponents<
|
||||
typename vtkm::cont::ArrayHandleStride<BaseComponentType>::WritePortalType>
|
||||
WritePortalForBaseComponentType() const
|
||||
{
|
||||
vtkm::IdComponent numComponents = this->GetNumberOfComponentsFlat();
|
||||
vtkm::cont::internal::ArrayPortalFromExtractedComponents<
|
||||
typename vtkm::cont::ArrayHandleStride<BaseComponentType>::WritePortalType>
|
||||
portal(numComponents);
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex)
|
||||
{
|
||||
auto array = this->ExtractComponent<BaseComponentType>(cIndex, vtkm::CopyFlag::Off);
|
||||
portal.AddArray(array, array.WritePortal());
|
||||
}
|
||||
return portal;
|
||||
}
|
||||
///@}
|
||||
|
||||
/// \brief Call a functor using the underlying array type.
|
||||
///
|
||||
/// `CastAndCall` attempts to cast the held array to a specific value type,
|
||||
|
@ -1,96 +0,0 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt for details.
|
||||
//
|
||||
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
// PURPOSE. See the above copyright notice for more information.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_cont_internal_ArrayPortalFromExtractedComponents_h
|
||||
#define vtk_m_cont_internal_ArrayPortalFromExtractedComponents_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
|
||||
#include <vtkm/internal/ArrayPortalHelpers.h>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
class UnknownArrayHandle;
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
/// `ArrayPortalFromExtractedComponents` is a convenience class that allows you to treat
|
||||
/// a group of arrays that were extracted from the components of an array and treat them
|
||||
/// like a portal to the array itself. It is used internally by `UnknownArrayHandle` to
|
||||
/// get read and write portals to the array
|
||||
///
|
||||
/// Note that this portal only works on the control environment.
|
||||
///
|
||||
template <typename PortalType>
|
||||
class ArrayPortalFromExtractedComponents
|
||||
{
|
||||
private:
|
||||
using T = typename PortalType::ValueType;
|
||||
std::vector<vtkm::cont::ArrayHandleStride<T>> Arrays;
|
||||
std::vector<PortalType> Portals;
|
||||
mutable std::vector<T> Values;
|
||||
|
||||
friend UnknownArrayHandle;
|
||||
|
||||
void AddArray(const vtkm::cont::ArrayHandleStride<T>& array, const PortalType& portal)
|
||||
{
|
||||
this->Arrays.push_back(array);
|
||||
this->Portals.push_back(portal);
|
||||
}
|
||||
|
||||
public:
|
||||
using ValueType = vtkm::VecCConst<T>;
|
||||
|
||||
ArrayPortalFromExtractedComponents(vtkm::IdComponent expectedArrays = 0)
|
||||
{
|
||||
this->Arrays.reserve(static_cast<std::size_t>(expectedArrays));
|
||||
this->Portals.reserve(static_cast<std::size_t>(expectedArrays));
|
||||
}
|
||||
|
||||
VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Portals[0].GetNumberOfValues(); }
|
||||
|
||||
VTKM_CONT ValueType Get(vtkm::Id index) const
|
||||
{
|
||||
// Note: this is not thread-safe
|
||||
this->Values.clear();
|
||||
for (auto&& portal : this->Portals)
|
||||
{
|
||||
this->Values.push_back(portal.Get(index));
|
||||
}
|
||||
return ValueType(this->Values.data(), static_cast<vtkm::IdComponent>(this->Values.size()));
|
||||
}
|
||||
|
||||
template <typename VecType,
|
||||
typename Writable = vtkm::internal::PortalSupportsSets<PortalType>,
|
||||
typename = typename std::enable_if<Writable::value>::type>
|
||||
VTKM_CONT void Set(vtkm::Id index, const VecType& value) const
|
||||
{
|
||||
using Traits = vtkm::VecTraits<VecType>;
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < Traits::GetNumberOfComponents(value); ++cIndex)
|
||||
{
|
||||
this->Portals[static_cast<std::size_t>(cIndex)].Set(index,
|
||||
Traits::GetComponent(value, index));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
||||
#endif //vtk_m_cont_internal_ArrayPortalFromExtractedComponents_h
|
@ -10,7 +10,6 @@
|
||||
|
||||
set(headers
|
||||
ArrayHandleExecutionManager.h
|
||||
ArrayPortalFromExtractedComponents.h
|
||||
ArrayPortalFromIterators.h
|
||||
ArrayTransfer.h
|
||||
AtomicInterfaceControl.h
|
||||
|
@ -443,14 +443,15 @@ void TryExtractComponent()
|
||||
|
||||
VTKM_TEST_ASSERT(unknownArray.GetNumberOfComponentsFlat() == FlatVec::NUM_COMPONENTS);
|
||||
|
||||
auto componentPortal = unknownArray.ReadPortalForBaseComponentType<ComponentType>();
|
||||
|
||||
auto originalPortal = originalArray.ReadPortal();
|
||||
auto extractedArray = unknownArray.ExtractArrayFromComponents<ComponentType>();
|
||||
VTKM_TEST_ASSERT(extractedArray.GetNumberOfComponents() == FlatVec::NUM_COMPONENTS);
|
||||
auto extractedPortal = extractedArray.ReadPortal();
|
||||
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
|
||||
{
|
||||
FlatVec originalData = originalPortal.Get(valueIndex);
|
||||
auto componentData = componentPortal.Get(valueIndex);
|
||||
VTKM_TEST_ASSERT(test_equal(originalData, componentData));
|
||||
auto extractedData = extractedPortal.Get(valueIndex);
|
||||
VTKM_TEST_ASSERT(test_equal(originalData, extractedData));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,8 @@ struct OutputArrayDataFunctor
|
||||
template <typename T>
|
||||
VTKM_CONT void operator()(T, const vtkm::cont::UnknownArrayHandle& array, std::ostream& out) const
|
||||
{
|
||||
auto portal = array.ReadPortalForBaseComponentType<T>();
|
||||
auto componentArray = array.ExtractArrayFromComponents<T>();
|
||||
auto portal = componentArray.ReadPortal();
|
||||
|
||||
vtkm::Id numValues = portal.GetNumberOfValues();
|
||||
for (vtkm::Id valueIndex = 0; valueIndex < numValues; ++valueIndex)
|
||||
|
Loading…
Reference in New Issue
Block a user