diff --git a/vtkm/cont/UnknownArrayHandle.h b/vtkm/cont/UnknownArrayHandle.h index 0ca3e3eee..b8123a792 100644 --- a/vtkm/cont/UnknownArrayHandle.h +++ b/vtkm/cont/UnknownArrayHandle.h @@ -16,11 +16,10 @@ #include #include #include +#include #include #include -#include - #include #include @@ -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, 3>`, then this method will tread the data as + /// if it was `Vec`. 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` 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 - VTKM_CONT vtkm::cont::internal::ArrayPortalFromExtractedComponents< - typename vtkm::cont::ArrayHandleStride::ReadPortalType> - ReadPortalForBaseComponentType() const + VTKM_CONT vtkm::cont::ArrayHandleRecombineVec ExtractArrayFromComponents( + vtkm::CopyFlag allowCopy = vtkm::CopyFlag::On) const { + vtkm::cont::ArrayHandleRecombineVec result; vtkm::IdComponent numComponents = this->GetNumberOfComponentsFlat(); - vtkm::cont::internal::ArrayPortalFromExtractedComponents< - typename vtkm::cont::ArrayHandleStride::ReadPortalType> - portal(numComponents); for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex) { - auto array = this->ExtractComponent(cIndex, vtkm::CopyFlag::On); - portal.AddArray(array, array.ReadPortal()); + result.AppendComponentArray(this->ExtractComponent(cIndex, allowCopy)); } - return portal; + return result; } - template - VTKM_CONT vtkm::cont::internal::ArrayPortalFromExtractedComponents< - typename vtkm::cont::ArrayHandleStride::WritePortalType> - WritePortalForBaseComponentType() const - { - vtkm::IdComponent numComponents = this->GetNumberOfComponentsFlat(); - vtkm::cont::internal::ArrayPortalFromExtractedComponents< - typename vtkm::cont::ArrayHandleStride::WritePortalType> - portal(numComponents); - for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex) - { - auto array = this->ExtractComponent(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, diff --git a/vtkm/cont/internal/ArrayPortalFromExtractedComponents.h b/vtkm/cont/internal/ArrayPortalFromExtractedComponents.h deleted file mode 100644 index 93a912802..000000000 --- a/vtkm/cont/internal/ArrayPortalFromExtractedComponents.h +++ /dev/null @@ -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 - -#include - -#include -#include - -#include - -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 -class ArrayPortalFromExtractedComponents -{ -private: - using T = typename PortalType::ValueType; - std::vector> Arrays; - std::vector Portals; - mutable std::vector Values; - - friend UnknownArrayHandle; - - void AddArray(const vtkm::cont::ArrayHandleStride& array, const PortalType& portal) - { - this->Arrays.push_back(array); - this->Portals.push_back(portal); - } - -public: - using ValueType = vtkm::VecCConst; - - ArrayPortalFromExtractedComponents(vtkm::IdComponent expectedArrays = 0) - { - this->Arrays.reserve(static_cast(expectedArrays)); - this->Portals.reserve(static_cast(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(this->Values.size())); - } - - template , - typename = typename std::enable_if::type> - VTKM_CONT void Set(vtkm::Id index, const VecType& value) const - { - using Traits = vtkm::VecTraits; - for (vtkm::IdComponent cIndex = 0; cIndex < Traits::GetNumberOfComponents(value); ++cIndex) - { - this->Portals[static_cast(cIndex)].Set(index, - Traits::GetComponent(value, index)); - } - } -}; - -} -} -} // namespace vtkm::cont::internal - -#endif //vtk_m_cont_internal_ArrayPortalFromExtractedComponents_h diff --git a/vtkm/cont/internal/CMakeLists.txt b/vtkm/cont/internal/CMakeLists.txt index e1e75ec53..5c876851b 100644 --- a/vtkm/cont/internal/CMakeLists.txt +++ b/vtkm/cont/internal/CMakeLists.txt @@ -10,7 +10,6 @@ set(headers ArrayHandleExecutionManager.h - ArrayPortalFromExtractedComponents.h ArrayPortalFromIterators.h ArrayTransfer.h AtomicInterfaceControl.h diff --git a/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx b/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx index b3593764f..28f036a93 100644 --- a/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx +++ b/vtkm/cont/testing/UnitTestUnknownArrayHandle.cxx @@ -443,14 +443,15 @@ void TryExtractComponent() VTKM_TEST_ASSERT(unknownArray.GetNumberOfComponentsFlat() == FlatVec::NUM_COMPONENTS); - auto componentPortal = unknownArray.ReadPortalForBaseComponentType(); - auto originalPortal = originalArray.ReadPortal(); + auto extractedArray = unknownArray.ExtractArrayFromComponents(); + 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)); } } diff --git a/vtkm/io/VTKDataSetWriter.cxx b/vtkm/io/VTKDataSetWriter.cxx index 142784150..6af59a9d4 100644 --- a/vtkm/io/VTKDataSetWriter.cxx +++ b/vtkm/io/VTKDataSetWriter.cxx @@ -86,7 +86,8 @@ struct OutputArrayDataFunctor template VTKM_CONT void operator()(T, const vtkm::cont::UnknownArrayHandle& array, std::ostream& out) const { - auto portal = array.ReadPortalForBaseComponentType(); + auto componentArray = array.ExtractArrayFromComponents(); + auto portal = componentArray.ReadPortal(); vtkm::Id numValues = portal.GetNumberOfValues(); for (vtkm::Id valueIndex = 0; valueIndex < numValues; ++valueIndex)