diff --git a/docs/changelog/arrayhandleconstant-extract-component.md b/docs/changelog/arrayhandleconstant-extract-component.md new file mode 100644 index 000000000..2d40ed30b --- /dev/null +++ b/docs/changelog/arrayhandleconstant-extract-component.md @@ -0,0 +1,9 @@ +# Added support for component extraction from ArrayHandleConstant better + +Previously, `ArrayHandleConstant` did not really support component +extraction. Instead, it let a fallback operation create a full array on +the CPU. + +Component extraction is now quite efficient for `ArrayHandleConstant`. It +creates a basic `ArrayHandle` with one entry and sets a modulo on the +`ArrayHandleStride` to access that value for all indices. diff --git a/vtkm/cont/ArrayHandleConstant.h b/vtkm/cont/ArrayHandleConstant.h index ed59e1318..b5b66faca 100644 --- a/vtkm/cont/ArrayHandleConstant.h +++ b/vtkm/cont/ArrayHandleConstant.h @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_ArrayHandleConstant_h #define vtk_m_cont_ArrayHandleConstant_h +#include #include #include @@ -100,6 +101,33 @@ vtkm::cont::ArrayHandleConstant make_ArrayHandleConstant(T value, vtkm::Id nu namespace internal { +template <> +struct VTKM_CONT_EXPORT ArrayExtractComponentImpl +{ + template + VTKM_CONT auto operator()(const vtkm::cont::ArrayHandle& src, + vtkm::IdComponent componentIndex, + vtkm::CopyFlag allowCopy) const + { + if (allowCopy != vtkm::CopyFlag::On) + { + throw vtkm::cont::ErrorBadValue( + "Cannot extract component of ArrayHandleConstant without copying. " + "(However, the whole array does not need to be copied.)"); + } + + vtkm::cont::ArrayHandleConstant srcArray = src; + + vtkm::VecFlat vecValue{ srcArray.GetValue() }; + + // Make a basic array with one entry (the constant value). + auto basicArray = vtkm::cont::make_ArrayHandle({ vecValue[componentIndex] }); + + // Set up a modulo = 1 so all indices go to this one value. + return vtkm::cont::make_ArrayHandleStride(basicArray, src.GetNumberOfValues(), 1, 0, 1, 1); + } +}; + template struct ArrayRangeComputeImpl; diff --git a/vtkm/cont/ArrayHandleStride.h b/vtkm/cont/ArrayHandleStride.h index ef48f7c6b..216c16000 100644 --- a/vtkm/cont/ArrayHandleStride.h +++ b/vtkm/cont/ArrayHandleStride.h @@ -375,6 +375,20 @@ public: } }; +/// @brief Create an array by adding a stride to a basic array. +/// +template +vtkm::cont::ArrayHandleStride make_ArrayHandleStride( + const vtkm::cont::ArrayHandle& array, + vtkm::Id numValues, + vtkm::Id stride, + vtkm::Id offset, + vtkm::Id modulo = 0, + vtkm::Id divisor = 1) +{ + return { array, numValues, stride, offset, modulo, divisor }; +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.h b/vtkm/cont/ArrayHandleUniformPointCoordinates.h index abf5e00d8..8f1eebd2c 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.h +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.h @@ -11,7 +11,6 @@ #define vtk_m_cont_ArrayHandleUniformPointCoordinates_h #include -#include #include #include @@ -68,9 +67,15 @@ public: VTKM_CONT vtkm::Vec3f GetSpacing() const; }; +template +class ArrayHandleStride; + namespace internal { +template +struct ArrayExtractComponentImpl; + template <> struct VTKM_CONT_EXPORT ArrayExtractComponentImpl { diff --git a/vtkm/cont/testing/UnitTestArrayExtractComponent.cxx b/vtkm/cont/testing/UnitTestArrayExtractComponent.cxx index 600408474..6e052276d 100644 --- a/vtkm/cont/testing/UnitTestArrayExtractComponent.cxx +++ b/vtkm/cont/testing/UnitTestArrayExtractComponent.cxx @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -283,6 +284,12 @@ void DoTest() CheckInputArray(array, vtkm::CopyFlag::On); } + { + std::cout << "ArrayHandleConstant" << std::endl; + vtkm::cont::ArrayHandleConstant array(TestValue(0, vtkm::Vec3f{}), ARRAY_SIZE); + CheckInputArray(array, vtkm::CopyFlag::On); + } + { std::cout << "Weird combination." << std::endl;