//============================================================================ // 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_ArrayHandleBasic_h #define vtk_m_cont_ArrayHandleBasic_h #include #include #include #include #include #include #include #include namespace vtkm { namespace cont { namespace internal { template class VTKM_ALWAYS_EXPORT Storage { public: using ReadPortalType = vtkm::internal::ArrayPortalBasicRead; using WritePortalType = vtkm::internal::ArrayPortalBasicWrite; VTKM_CONT static std::vector CreateBuffers() { return std::vector(1); } VTKM_CONT static void ResizeBuffers(vtkm::Id numValues, const std::vector& buffers, vtkm::CopyFlag preserve, vtkm::cont::Token& token) { buffers[0].SetNumberOfBytes( vtkm::internal::NumberOfValuesToNumberOfBytes(numValues), preserve, token); } VTKM_CONT static vtkm::IdComponent GetNumberOfComponentsFlat( const std::vector&) { return vtkm::VecFlat::NUM_COMPONENTS; } VTKM_CONT static vtkm::Id GetNumberOfValues( const std::vector& buffers) { VTKM_ASSERT(buffers.size() == 1); return static_cast(buffers[0].GetNumberOfBytes() / static_cast(sizeof(T))); } VTKM_CONT static void Fill(const std::vector& buffers, const T& fillValue, vtkm::Id startIndex, vtkm::Id endIndex, vtkm::cont::Token& token) { VTKM_ASSERT(buffers.size() == 1); constexpr vtkm::BufferSizeType fillValueSize = static_cast(sizeof(fillValue)); buffers[0].Fill( &fillValue, fillValueSize, startIndex * fillValueSize, endIndex * fillValueSize, token); } VTKM_CONT static ReadPortalType CreateReadPortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { VTKM_ASSERT(buffers.size() == 1); return ReadPortalType(reinterpret_cast(buffers[0].ReadPointerDevice(device, token)), GetNumberOfValues(buffers)); } VTKM_CONT static WritePortalType CreateWritePortal( const std::vector& buffers, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) { VTKM_ASSERT(buffers.size() == 1); return WritePortalType(reinterpret_cast(buffers[0].WritePointerDevice(device, token)), GetNumberOfValues(buffers)); } }; } // namespace internal /// @brief Basic array storage for an array handle. /// /// This array handle references a standard C array. It provides a level /// of safety and management across devices. /// This is the default used when no storage is specified. Using this subclass /// allows access to the underlying raw array. template class VTKM_ALWAYS_EXPORT ArrayHandleBasic : public ArrayHandle { public: VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleBasic, (ArrayHandleBasic), (ArrayHandle)); ArrayHandleBasic( T* array, vtkm::Id numberOfValues, vtkm::cont::internal::BufferInfo::Deleter deleter, vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::InvalidRealloc) : Superclass(std::vector{ vtkm::cont::internal::MakeBuffer( vtkm::cont::DeviceAdapterTagUndefined{}, array, array, vtkm::internal::NumberOfValuesToNumberOfBytes(numberOfValues), deleter, reallocater) }) { } ArrayHandleBasic( T* array, vtkm::Id numberOfValues, vtkm::cont::DeviceAdapterId device, vtkm::cont::internal::BufferInfo::Deleter deleter, vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::InvalidRealloc) : Superclass(std::vector{ vtkm::cont::internal::MakeBuffer( device, array, array, vtkm::internal::NumberOfValuesToNumberOfBytes(numberOfValues), deleter, reallocater) }) { } ArrayHandleBasic( T* array, void* container, vtkm::Id numberOfValues, vtkm::cont::internal::BufferInfo::Deleter deleter, vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::InvalidRealloc) : Superclass(std::vector{ vtkm::cont::internal::MakeBuffer( vtkm::cont::DeviceAdapterTagUndefined{}, array, container, vtkm::internal::NumberOfValuesToNumberOfBytes(numberOfValues), deleter, reallocater) }) { } ArrayHandleBasic( T* array, void* container, vtkm::Id numberOfValues, vtkm::cont::DeviceAdapterId device, vtkm::cont::internal::BufferInfo::Deleter deleter, vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::InvalidRealloc) : Superclass(std::vector{ vtkm::cont::internal::MakeBuffer( device, array, container, vtkm::internal::NumberOfValuesToNumberOfBytes(numberOfValues), deleter, reallocater) }) { } /// @brief Gets raw access to the `ArrayHandle`'s data. /// /// Note that the returned array may become invalidated by other operations on the ArryHandle. /// const T* GetReadPointer() const { vtkm::cont::Token token; return this->GetReadPointer(token); } /// @brief Gets raw access to the `ArrayHandle`'s data. /// /// @param token When a `vtkm::cont::Token` is provided, the array is locked /// from being used by any write operations until the token goes out of scope. /// const T* GetReadPointer(vtkm::cont::Token& token) const { return reinterpret_cast(this->GetBuffers()[0].ReadPointerHost(token)); } /// @brief Gets raw write access to the `ArrayHandle`'s data. /// /// Note that the returned array may become invalidated by other operations on the ArryHandle. /// T* GetWritePointer() const { vtkm::cont::Token token; return this->GetWritePointer(token); } /// @brief Gets raw write access to the `ArrayHandle`'s data. /// /// @param token When a `vtkm::cont::Token` is provided, the array is locked /// from being used by any read or write operations until the token goes out of scope. /// T* GetWritePointer(vtkm::cont::Token& token) const { return reinterpret_cast(this->GetBuffers()[0].WritePointerHost(token)); } /// @brief Gets raw access to the `ArrayHandle`'s data on a particular device. /// /// Note that the returned array may become invalidated by other operations on the ArryHandle. /// /// @param device The device ID or device tag specifying on which device the array will /// be valid on. /// const T* GetReadPointer(vtkm::cont::DeviceAdapterId device) const { vtkm::cont::Token token; return this->GetReadPointer(device, token); } /// @brief Gets raw access to the `ArrayHandle`'s data. /// /// @param device The device ID or device tag specifying on which device the array will /// be valid on. /// @param token When a `vtkm::cont::Token` is provided, the array is locked /// from being used by any write operations until the token goes out of scope. /// const T* GetReadPointer(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const { return reinterpret_cast(this->GetBuffers()[0].ReadPointerDevice(device, token)); } /// @brief Gets raw write access to the `ArrayHandle`'s data. /// /// Note that the returned array may become invalidated by other operations on the ArryHandle. /// /// @param device The device ID or device tag specifying on which device the array will /// be valid on. /// T* GetWritePointer(vtkm::cont::DeviceAdapterId device) const { vtkm::cont::Token token; return this->GetWritePointer(device, token); } /// @brief Gets raw write access to the `ArrayHandle`'s data. /// /// @param device The device ID or device tag specifying on which device the array will /// be valid on. /// @param token When a `vtkm::cont::Token` is provided, the array is locked /// from being used by any read or write operations until the token goes out of scope. /// T* GetWritePointer(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token) const { return reinterpret_cast(this->GetBuffers()[0].WritePointerDevice(device, token)); } }; /// A convenience function for creating an ArrayHandle from a standard C array. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandle(const T* array, vtkm::Id numberOfValues, vtkm::CopyFlag copy) { if (copy == vtkm::CopyFlag::On) { vtkm::cont::ArrayHandleBasic handle; handle.Allocate(numberOfValues); std::copy( array, array + numberOfValues, vtkm::cont::ArrayPortalToIteratorBegin(handle.WritePortal())); return handle; } else { return vtkm::cont::ArrayHandleBasic(const_cast(array), numberOfValues, [](void*) {}); } } /// A convenience function to move a user-allocated array into an `ArrayHandle`. /// The provided array pointer will be reset to `nullptr`. /// If the array was not allocated with the `new[]` operator, then deleter and reallocater /// functions must be provided. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandleMove( T*& array, vtkm::Id numberOfValues, vtkm::cont::internal::BufferInfo::Deleter deleter = internal::SimpleArrayDeleter, vtkm::cont::internal::BufferInfo::Reallocater reallocater = internal::SimpleArrayReallocater) { vtkm::cont::ArrayHandleBasic arrayHandle(array, numberOfValues, deleter, reallocater); array = nullptr; return arrayHandle; } /// A convenience function for creating an ArrayHandle from an std::vector. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandle(const std::vector& array, vtkm::CopyFlag copy) { if (!array.empty()) { return make_ArrayHandle(array.data(), static_cast(array.size()), copy); } else { // Vector empty. Just return an empty array handle. return vtkm::cont::ArrayHandle(); } } /// Move an std::vector into an ArrayHandle. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandleMove(std::vector&& array) { using vector_type = std::vector; vector_type* container = new vector_type(std::move(array)); return vtkm::cont::ArrayHandleBasic(container->data(), container, static_cast(container->size()), internal::StdVectorDeleter, internal::StdVectorReallocater); } /// Move an std::vector into an ArrayHandle. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandle(std::vector&& array, vtkm::CopyFlag vtkmNotUsed(copy)) { return make_ArrayHandleMove(array); } /// Create an ArrayHandle directly from an initializer list of values. /// template VTKM_CONT vtkm::cont::ArrayHandleBasic make_ArrayHandle(std::initializer_list&& values) { return make_ArrayHandle(values.begin(), static_cast(values.size()), vtkm::CopyFlag::On); } } } // namespace vtkm::cont //============================================================================= // Specializations of serialization related classes /// @cond SERIALIZATION namespace vtkm { namespace cont { template struct SerializableTypeString> { static VTKM_CONT const std::string& Get() { static std::string name = "AH<" + SerializableTypeString::Get() + ">"; return name; } }; template struct SerializableTypeString> : SerializableTypeString> { }; } } // vtkm::cont namespace mangled_diy_namespace { template struct Serialization> { static VTKM_CONT void save(BinaryBuffer& bb, const vtkm::cont::ArrayHandle& obj) { vtkmdiy::save(bb, obj.GetBuffers()[0]); } static VTKM_CONT void load(BinaryBuffer& bb, vtkm::cont::ArrayHandle& obj) { vtkm::cont::internal::Buffer buffer; vtkmdiy::load(bb, buffer); obj = vtkm::cont::ArrayHandle( vtkm::cont::internal::CreateBuffers(buffer)); } }; template struct Serialization> : Serialization> { }; } // diy /// @endcond SERIALIZATION #ifndef vtk_m_cont_ArrayHandleBasic_cxx /// @cond /// Make doxygen ignore this section namespace vtkm { namespace cont { namespace internal { #define VTKM_STORAGE_EXPORT(Type) \ extern template class VTKM_CONT_TEMPLATE_EXPORT Storage; \ extern template class VTKM_CONT_TEMPLATE_EXPORT Storage, StorageTagBasic>; \ extern template class VTKM_CONT_TEMPLATE_EXPORT Storage, StorageTagBasic>; \ extern template class VTKM_CONT_TEMPLATE_EXPORT Storage, StorageTagBasic>; VTKM_STORAGE_EXPORT(char) VTKM_STORAGE_EXPORT(vtkm::Int8) VTKM_STORAGE_EXPORT(vtkm::UInt8) VTKM_STORAGE_EXPORT(vtkm::Int16) VTKM_STORAGE_EXPORT(vtkm::UInt16) VTKM_STORAGE_EXPORT(vtkm::Int32) VTKM_STORAGE_EXPORT(vtkm::UInt32) VTKM_STORAGE_EXPORT(vtkm::Int64) VTKM_STORAGE_EXPORT(vtkm::UInt64) VTKM_STORAGE_EXPORT(vtkm::Float32) VTKM_STORAGE_EXPORT(vtkm::Float64) #undef VTKM_STORAGE_EXPORT } // namespace internal #define VTKM_ARRAYHANDLE_EXPORT(Type) \ extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle; \ extern template class VTKM_CONT_TEMPLATE_EXPORT \ ArrayHandle, StorageTagBasic>; \ extern template class VTKM_CONT_TEMPLATE_EXPORT \ ArrayHandle, StorageTagBasic>; \ extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle, StorageTagBasic>; VTKM_ARRAYHANDLE_EXPORT(char) VTKM_ARRAYHANDLE_EXPORT(vtkm::Int8) VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt8) VTKM_ARRAYHANDLE_EXPORT(vtkm::Int16) VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt16) VTKM_ARRAYHANDLE_EXPORT(vtkm::Int32) VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt32) VTKM_ARRAYHANDLE_EXPORT(vtkm::Int64) VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt64) VTKM_ARRAYHANDLE_EXPORT(vtkm::Float32) VTKM_ARRAYHANDLE_EXPORT(vtkm::Float64) #undef VTKM_ARRAYHANDLE_EXPORT } } // end vtkm::cont /// @endcond #endif // !vtk_m_cont_ArrayHandleBasic_cxx #endif //vtk_m_cont_ArrayHandleBasic_h