//============================================================================ // 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_ArrayHandleView_h #define vtk_m_cont_ArrayHandleView_h #include #include #include #include namespace vtkm { namespace internal { struct ViewIndices { vtkm::Id StartIndex = 0; vtkm::Id NumberOfValues = 0; ViewIndices() = default; ViewIndices(vtkm::Id start, vtkm::Id numValues) : StartIndex(start) , NumberOfValues(numValues) { } }; template class ArrayPortalView { using Writable = vtkm::internal::PortalSupportsSets; public: using ValueType = typename TargetPortalType::ValueType; VTKM_EXEC_CONT ArrayPortalView() {} VTKM_EXEC_CONT ArrayPortalView(const TargetPortalType& targetPortal, ViewIndices indices) : TargetPortal(targetPortal) , Indices(indices) { } template VTKM_EXEC_CONT ArrayPortalView(const ArrayPortalView& otherPortal) : TargetPortal(otherPortal.GetTargetPortal()) , Indices(otherPortal.GetStartIndex(), otherPortal.GetNumberOfValues()) { } VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->Indices.NumberOfValues; } VTKM_EXEC_CONT ValueType Get(vtkm::Id index) const { return this->TargetPortal.Get(index + this->GetStartIndex()); } template ::type> VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const { this->TargetPortal.Set(index + this->GetStartIndex(), value); } VTKM_EXEC_CONT const TargetPortalType& GetTargetPortal() const { return this->TargetPortal; } VTKM_EXEC_CONT vtkm::Id GetStartIndex() const { return this->Indices.StartIndex; } private: TargetPortalType TargetPortal; ViewIndices Indices; }; } // namespace internal namespace cont { template struct VTKM_ALWAYS_EXPORT StorageTagView { }; namespace internal { template class Storage> { using ArrayHandleType = vtkm::cont::ArrayHandle; using SourceStorage = Storage; static std::vector SourceBuffers( const std::vector& buffers) { return std::vector(buffers.begin() + 1, buffers.end()); } public: VTKM_STORAGE_NO_RESIZE; using ReadPortalType = vtkm::internal::ArrayPortalView; using WritePortalType = vtkm::internal::ArrayPortalView; VTKM_CONT static vtkm::Id GetNumberOfValues( const std::vector& buffers) { return buffers[0].GetMetaData().NumberOfValues; } VTKM_CONT static ReadPortalType CreateReadPortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { vtkm::internal::ViewIndices indices = buffers[0].GetMetaData(); return ReadPortalType(SourceStorage::CreateReadPortal(SourceBuffers(buffers), device, token), indices); } VTKM_CONT static void Fill(const std::vector& buffers, const T& fillValue, vtkm::Id startIndex, vtkm::Id endIndex, vtkm::cont::Token& token) { vtkm::internal::ViewIndices indices = buffers[0].GetMetaData(); vtkm::Id adjustedStartIndex = startIndex + indices.StartIndex; vtkm::Id adjustedEndIndex = (endIndex < indices.NumberOfValues) ? endIndex + indices.StartIndex : indices.NumberOfValues + indices.StartIndex; SourceStorage::Fill( SourceBuffers(buffers), fillValue, adjustedStartIndex, adjustedEndIndex, token); } VTKM_CONT static WritePortalType CreateWritePortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { vtkm::internal::ViewIndices indices = buffers[0].GetMetaData(); return WritePortalType(SourceStorage::CreateWritePortal(SourceBuffers(buffers), device, token), indices); } VTKM_CONT static std::vector CreateBuffers( vtkm::Id startIndex = 0, vtkm::Id numValues = 0, const ArrayHandleType& array = ArrayHandleType{}) { return vtkm::cont::internal::CreateBuffers(vtkm::internal::ViewIndices(startIndex, numValues), array); } VTKM_CONT static ArrayHandleType GetSourceArray( const std::vector& buffers) { return ArrayHandleType(SourceBuffers(buffers)); } VTKM_CONT static vtkm::Id GetStartIndex(const std::vector& buffers) { return buffers[0].GetMetaData().StartIndex; } }; } // namespace internal template class ArrayHandleView : public vtkm::cont::ArrayHandle> { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); public: VTKM_ARRAY_HANDLE_SUBCLASS( ArrayHandleView, (ArrayHandleView), (vtkm::cont::ArrayHandle>)); private: using StorageType = vtkm::cont::internal::Storage; public: VTKM_CONT ArrayHandleView(const ArrayHandleType& array, vtkm::Id startIndex, vtkm::Id numValues) : Superclass(StorageType::CreateBuffers(startIndex, numValues, array)) { } VTKM_CONT ArrayHandleType GetSourceArray() const { return this->GetStorage().GetSourceArray(this->GetBuffers()); } VTKM_CONT vtkm::Id GetStartIndex() const { return this->GetStorage().GetStartIndex(this->GetBuffers()); } }; template ArrayHandleView make_ArrayHandleView(const ArrayHandleType& array, vtkm::Id startIndex, vtkm::Id numValues) { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); return ArrayHandleView(array, startIndex, numValues); } namespace internal { // Superclass will inherit the ArrayExtractComponentImplInefficient property if // the sub-storage is inefficient (thus making everything inefficient). template struct ArrayExtractComponentImpl> : vtkm::cont::internal::ArrayExtractComponentImpl { template using StrideArrayType = vtkm::cont::ArrayHandleStride::BaseComponentType>; template StrideArrayType operator()( const vtkm::cont::ArrayHandle>& src, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy) const { vtkm::cont::ArrayHandleView> srcArray(src); StrideArrayType subArray = ArrayExtractComponentImpl{}(srcArray.GetSourceArray(), componentIndex, allowCopy); // Narrow the array by adjusting the size and offset. return StrideArrayType(subArray.GetBasicArray(), srcArray.GetNumberOfValues(), subArray.GetStride(), subArray.GetOffset() + (subArray.GetStride() * srcArray.GetStartIndex()), subArray.GetModulo(), subArray.GetDivisor()); } }; } // namespace internal } } // namespace vtkm::cont #endif //vtk_m_cont_ArrayHandleView_h