2019-04-15 23:24:21 +00:00
|
|
|
//============================================================================
|
2019-03-07 21:45:21 +00:00
|
|
|
// 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.
|
2019-04-15 23:24:21 +00:00
|
|
|
//============================================================================
|
2019-03-07 21:45:21 +00:00
|
|
|
#ifndef vtk_m_cont_ArrayHandleBitField_h
|
|
|
|
#define vtk_m_cont_ArrayHandleBitField_h
|
|
|
|
|
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
|
|
|
#include <vtkm/cont/BitField.h>
|
|
|
|
#include <vtkm/cont/Storage.h>
|
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
|
|
|
|
template <typename BitPortalType>
|
|
|
|
class ArrayPortalBitField
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
using ValueType = bool;
|
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
2020-08-17 14:18:24 +00:00
|
|
|
explicit ArrayPortalBitField(const BitPortalType& portal) noexcept
|
|
|
|
: BitPortal{ portal }
|
|
|
|
{
|
|
|
|
}
|
2019-03-07 21:45:21 +00:00
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
2020-08-17 14:18:24 +00:00
|
|
|
explicit ArrayPortalBitField(BitPortalType&& portal) noexcept
|
|
|
|
: BitPortal{ std::move(portal) }
|
|
|
|
{
|
|
|
|
}
|
2019-03-07 21:45:21 +00:00
|
|
|
|
|
|
|
ArrayPortalBitField() noexcept = default;
|
|
|
|
ArrayPortalBitField(const ArrayPortalBitField&) noexcept = default;
|
|
|
|
ArrayPortalBitField(ArrayPortalBitField&&) noexcept = default;
|
|
|
|
ArrayPortalBitField& operator=(const ArrayPortalBitField&) noexcept = default;
|
|
|
|
ArrayPortalBitField& operator=(ArrayPortalBitField&&) noexcept = default;
|
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
|
|
|
vtkm::Id GetNumberOfValues() const noexcept { return this->BitPortal.GetNumberOfBits(); }
|
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
|
|
|
ValueType Get(vtkm::Id index) const noexcept { return this->BitPortal.GetBit(index); }
|
|
|
|
|
|
|
|
VTKM_EXEC_CONT
|
|
|
|
void Set(vtkm::Id index, ValueType value) const
|
|
|
|
{
|
|
|
|
// Use an atomic set so we don't clash with other threads writing nearby
|
|
|
|
// bits.
|
|
|
|
this->BitPortal.SetBitAtomic(index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
BitPortalType BitPortal;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct VTKM_ALWAYS_EXPORT StorageTagBitField
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
class Storage<bool, StorageTagBitField>
|
|
|
|
{
|
2020-08-19 21:44:11 +00:00
|
|
|
using BitPortalType = vtkm::cont::detail::BitPortal;
|
|
|
|
using BitPortalConstType = vtkm::cont::detail::BitPortalConst;
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2020-08-17 21:37:42 +00:00
|
|
|
using WordType = vtkm::WordTypeDefault;
|
|
|
|
static constexpr vtkm::Id BlockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
|
|
|
|
VTKM_STATIC_ASSERT(BlockSize >= static_cast<vtkm::Id>(sizeof(WordType)));
|
|
|
|
|
2019-03-07 21:45:21 +00:00
|
|
|
public:
|
2020-08-17 21:37:42 +00:00
|
|
|
using ReadPortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalConstType>;
|
|
|
|
using WritePortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalType>;
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
|
|
|
|
{
|
|
|
|
return std::vector<vtkm::cont::internal::Buffer>(1);
|
|
|
|
}
|
2020-08-17 21:37:42 +00:00
|
|
|
|
2020-08-25 15:36:07 +00:00
|
|
|
VTKM_CONT static void ResizeBuffers(vtkm::Id numberOfBits,
|
2022-06-28 20:26:38 +00:00
|
|
|
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
2020-08-25 15:36:07 +00:00
|
|
|
vtkm::CopyFlag preserve,
|
|
|
|
vtkm::cont::Token& token)
|
2020-08-17 21:37:42 +00:00
|
|
|
{
|
2020-08-24 21:26:57 +00:00
|
|
|
const vtkm::Id bytesNeeded = (numberOfBits + CHAR_BIT - 1) / CHAR_BIT;
|
2020-08-17 21:37:42 +00:00
|
|
|
const vtkm::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
|
|
|
|
const vtkm::Id numBytes = blocksNeeded * BlockSize;
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2020-08-24 21:26:57 +00:00
|
|
|
VTKM_LOG_F(vtkm::cont::LogLevel::MemCont,
|
|
|
|
"BitField Allocation: %llu bits, blocked up to %s bytes.",
|
|
|
|
static_cast<unsigned long long>(numberOfBits),
|
|
|
|
vtkm::cont::GetSizeString(static_cast<vtkm::UInt64>(numBytes)).c_str());
|
|
|
|
|
2020-08-17 21:37:42 +00:00
|
|
|
buffers[0].SetNumberOfBytes(numBytes, preserve, token);
|
2020-11-10 23:22:05 +00:00
|
|
|
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits = numberOfBits;
|
2020-08-17 21:37:42 +00:00
|
|
|
}
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2023-10-03 14:31:38 +00:00
|
|
|
VTKM_CONT static vtkm::IdComponent GetNumberOfComponentsFlat(
|
|
|
|
const std::vector<vtkm::cont::internal::Buffer>&)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_CONT static vtkm::Id GetNumberOfValues(
|
|
|
|
const std::vector<vtkm::cont::internal::Buffer>& buffers)
|
2020-08-17 21:37:42 +00:00
|
|
|
{
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_ASSERT(buffers.size() == 1);
|
2020-11-10 23:22:05 +00:00
|
|
|
vtkm::Id numberOfBits =
|
|
|
|
buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits;
|
2020-08-24 21:26:57 +00:00
|
|
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
|
|
|
return numberOfBits;
|
2020-08-17 21:37:42 +00:00
|
|
|
}
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
2022-01-04 16:29:12 +00:00
|
|
|
bool fillValue,
|
|
|
|
vtkm::Id startBit,
|
2022-01-11 14:15:41 +00:00
|
|
|
vtkm::Id endBit,
|
2022-01-04 16:29:12 +00:00
|
|
|
vtkm::cont::Token& token)
|
|
|
|
{
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_ASSERT(buffers.size() == 1);
|
2022-01-04 16:29:12 +00:00
|
|
|
constexpr vtkm::BufferSizeType wordTypeSize =
|
|
|
|
static_cast<vtkm::BufferSizeType>(sizeof(WordType));
|
2022-01-11 14:15:41 +00:00
|
|
|
constexpr vtkm::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT;
|
|
|
|
// Special case where filling to end of array.
|
|
|
|
vtkm::Id totalBitsInArray = GetNumberOfValues(buffers);
|
|
|
|
if (endBit >= totalBitsInArray)
|
|
|
|
{
|
|
|
|
endBit = ((totalBitsInArray + (wordNumBits - 1)) / wordNumBits) * wordNumBits;
|
|
|
|
}
|
|
|
|
if (((startBit % wordNumBits) == 0) && ((endBit % wordNumBits) == 0))
|
2022-01-04 16:29:12 +00:00
|
|
|
{
|
|
|
|
WordType fillWord = (fillValue ? ~WordType{ 0 } : WordType{ 0 });
|
2022-01-11 14:15:41 +00:00
|
|
|
buffers[0].Fill(&fillWord, wordTypeSize, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
|
2022-01-04 16:29:12 +00:00
|
|
|
}
|
2022-01-11 14:15:41 +00:00
|
|
|
else if (((startBit % CHAR_BIT) == 0) && ((endBit % CHAR_BIT) == 0))
|
2022-01-04 16:29:12 +00:00
|
|
|
{
|
|
|
|
vtkm::UInt8 fillWord = (fillValue ? ~vtkm::UInt8{ 0 } : vtkm::UInt8{ 0 });
|
2022-01-11 14:15:41 +00:00
|
|
|
buffers[0].Fill(&fillWord, 1, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
|
2022-01-04 16:29:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadValue("Can only fill ArrayHandleBitField on 8-bit boundaries.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_CONT static ReadPortalType CreateReadPortal(
|
|
|
|
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
|
|
|
vtkm::cont::DeviceAdapterId device,
|
|
|
|
vtkm::cont::Token& token)
|
2020-08-17 21:37:42 +00:00
|
|
|
{
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_ASSERT(buffers.size() == 1);
|
2020-08-25 15:36:07 +00:00
|
|
|
vtkm::Id numberOfBits = GetNumberOfValues(buffers);
|
2020-08-24 21:26:57 +00:00
|
|
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
2019-03-07 21:45:21 +00:00
|
|
|
|
2020-08-17 21:37:42 +00:00
|
|
|
return ReadPortalType(
|
2020-08-24 21:26:57 +00:00
|
|
|
BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
|
2020-08-17 21:37:42 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_CONT static WritePortalType CreateWritePortal(
|
|
|
|
const std::vector<vtkm::cont::internal::Buffer>& buffers,
|
|
|
|
vtkm::cont::DeviceAdapterId device,
|
|
|
|
vtkm::cont::Token& token)
|
2020-08-17 21:37:42 +00:00
|
|
|
{
|
2022-06-28 20:26:38 +00:00
|
|
|
VTKM_ASSERT(buffers.size() == 1);
|
2020-08-25 15:36:07 +00:00
|
|
|
vtkm::Id numberOfBits = GetNumberOfValues(buffers);
|
2020-08-24 21:26:57 +00:00
|
|
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
2020-08-17 21:37:42 +00:00
|
|
|
|
|
|
|
return WritePortalType(
|
2020-08-24 21:26:57 +00:00
|
|
|
BitPortalType(buffers[0].WritePointerDevice(device, token), numberOfBits));
|
2020-08-17 21:37:42 +00:00
|
|
|
}
|
2019-03-07 21:45:21 +00:00
|
|
|
};
|
|
|
|
|
2020-08-17 21:37:42 +00:00
|
|
|
} // end namespace internal
|
|
|
|
|
|
|
|
|
2019-03-07 21:45:21 +00:00
|
|
|
/// The ArrayHandleBitField class is a boolean-valued ArrayHandle that is backed
|
|
|
|
/// by a BitField.
|
|
|
|
///
|
|
|
|
class ArrayHandleBitField : public ArrayHandle<bool, internal::StorageTagBitField>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VTKM_ARRAY_HANDLE_SUBCLASS_NT(ArrayHandleBitField,
|
|
|
|
(ArrayHandle<bool, internal::StorageTagBitField>));
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
explicit ArrayHandleBitField(const vtkm::cont::BitField& bitField)
|
2020-08-24 21:26:57 +00:00
|
|
|
: Superclass(std::vector<vtkm::cont::internal::Buffer>(1, bitField.GetBuffer()))
|
2019-03-07 21:45:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
VTKM_CONT inline vtkm::cont::ArrayHandleBitField make_ArrayHandleBitField(
|
|
|
|
const vtkm::cont::BitField& bitField)
|
|
|
|
{
|
|
|
|
return ArrayHandleBitField{ bitField };
|
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_CONT inline vtkm::cont::ArrayHandleBitField make_ArrayHandleBitField(
|
|
|
|
vtkm::cont::BitField&& bitField) noexcept
|
|
|
|
{
|
|
|
|
return ArrayHandleBitField{ std::move(bitField) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // end namespace vtkm::cont
|
|
|
|
|
|
|
|
#endif // vtk_m_cont_ArrayHandleBitField_h
|