VTK-m  2.1
ArrayHandleBitField.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_cont_ArrayHandleBitField_h
11 #define vtk_m_cont_ArrayHandleBitField_h
12 
13 #include <vtkm/cont/ArrayHandle.h>
14 #include <vtkm/cont/BitField.h>
15 #include <vtkm/cont/Storage.h>
16 
17 namespace vtkm
18 {
19 namespace cont
20 {
21 
22 namespace internal
23 {
24 
25 template <typename BitPortalType>
26 class ArrayPortalBitField
27 {
28 public:
29  using ValueType = bool;
30 
32  explicit ArrayPortalBitField(const BitPortalType& portal) noexcept
33  : BitPortal{ portal }
34  {
35  }
36 
38  explicit ArrayPortalBitField(BitPortalType&& portal) noexcept
39  : BitPortal{ std::move(portal) }
40  {
41  }
42 
43  ArrayPortalBitField() noexcept = default;
44  ArrayPortalBitField(const ArrayPortalBitField&) noexcept = default;
45  ArrayPortalBitField(ArrayPortalBitField&&) noexcept = default;
46  ArrayPortalBitField& operator=(const ArrayPortalBitField&) noexcept = default;
47  ArrayPortalBitField& operator=(ArrayPortalBitField&&) noexcept = default;
48 
50  vtkm::Id GetNumberOfValues() const noexcept { return this->BitPortal.GetNumberOfBits(); }
51 
53  ValueType Get(vtkm::Id index) const noexcept { return this->BitPortal.GetBit(index); }
54 
56  void Set(vtkm::Id index, ValueType value) const
57  {
58  // Use an atomic set so we don't clash with other threads writing nearby
59  // bits.
60  this->BitPortal.SetBitAtomic(index, value);
61  }
62 
63 private:
64  BitPortalType BitPortal;
65 };
66 
67 struct VTKM_ALWAYS_EXPORT StorageTagBitField
68 {
69 };
70 
71 template <>
72 class Storage<bool, StorageTagBitField>
73 {
74  using BitPortalType = vtkm::cont::detail::BitPortal;
75  using BitPortalConstType = vtkm::cont::detail::BitPortalConst;
76 
77  using WordType = vtkm::WordTypeDefault;
78  static constexpr vtkm::Id BlockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
79  VTKM_STATIC_ASSERT(BlockSize >= static_cast<vtkm::Id>(sizeof(WordType)));
80 
81 public:
82  using ReadPortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalConstType>;
83  using WritePortalType = vtkm::cont::internal::ArrayPortalBitField<BitPortalType>;
84 
85  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer> CreateBuffers()
86  {
87  return std::vector<vtkm::cont::internal::Buffer>(1);
88  }
89 
90  VTKM_CONT static void ResizeBuffers(vtkm::Id numberOfBits,
91  const std::vector<vtkm::cont::internal::Buffer>& buffers,
92  vtkm::CopyFlag preserve,
93  vtkm::cont::Token& token)
94  {
95  const vtkm::Id bytesNeeded = (numberOfBits + CHAR_BIT - 1) / CHAR_BIT;
96  const vtkm::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
97  const vtkm::Id numBytes = blocksNeeded * BlockSize;
98 
100  "BitField Allocation: %llu bits, blocked up to %s bytes.",
101  static_cast<unsigned long long>(numberOfBits),
102  vtkm::cont::GetSizeString(static_cast<vtkm::UInt64>(numBytes)).c_str());
103 
104  buffers[0].SetNumberOfBytes(numBytes, preserve, token);
105  buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits = numberOfBits;
106  }
107 
108  VTKM_CONT static vtkm::IdComponent GetNumberOfComponentsFlat(
109  const std::vector<vtkm::cont::internal::Buffer>&)
110  {
111  return 1;
112  }
113 
114  VTKM_CONT static vtkm::Id GetNumberOfValues(
115  const std::vector<vtkm::cont::internal::Buffer>& buffers)
116  {
117  VTKM_ASSERT(buffers.size() == 1);
118  vtkm::Id numberOfBits =
119  buffers[0].GetMetaData<vtkm::cont::internal::BitFieldMetaData>().NumberOfBits;
120  VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
121  return numberOfBits;
122  }
123 
124  VTKM_CONT static void Fill(const std::vector<vtkm::cont::internal::Buffer>& buffers,
125  bool fillValue,
126  vtkm::Id startBit,
127  vtkm::Id endBit,
128  vtkm::cont::Token& token)
129  {
130  VTKM_ASSERT(buffers.size() == 1);
131  constexpr vtkm::BufferSizeType wordTypeSize =
132  static_cast<vtkm::BufferSizeType>(sizeof(WordType));
133  constexpr vtkm::BufferSizeType wordNumBits = wordTypeSize * CHAR_BIT;
134  // Special case where filling to end of array.
135  vtkm::Id totalBitsInArray = GetNumberOfValues(buffers);
136  if (endBit >= totalBitsInArray)
137  {
138  endBit = ((totalBitsInArray + (wordNumBits - 1)) / wordNumBits) * wordNumBits;
139  }
140  if (((startBit % wordNumBits) == 0) && ((endBit % wordNumBits) == 0))
141  {
142  WordType fillWord = (fillValue ? ~WordType{ 0 } : WordType{ 0 });
143  buffers[0].Fill(&fillWord, wordTypeSize, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
144  }
145  else if (((startBit % CHAR_BIT) == 0) && ((endBit % CHAR_BIT) == 0))
146  {
147  vtkm::UInt8 fillWord = (fillValue ? ~vtkm::UInt8{ 0 } : vtkm::UInt8{ 0 });
148  buffers[0].Fill(&fillWord, 1, startBit / CHAR_BIT, endBit / CHAR_BIT, token);
149  }
150  else
151  {
152  throw vtkm::cont::ErrorBadValue("Can only fill ArrayHandleBitField on 8-bit boundaries.");
153  }
154  }
155 
156  VTKM_CONT static ReadPortalType CreateReadPortal(
157  const std::vector<vtkm::cont::internal::Buffer>& buffers,
159  vtkm::cont::Token& token)
160  {
161  VTKM_ASSERT(buffers.size() == 1);
162  vtkm::Id numberOfBits = GetNumberOfValues(buffers);
163  VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
164 
165  return ReadPortalType(
166  BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
167  }
168 
169  VTKM_CONT static WritePortalType CreateWritePortal(
170  const std::vector<vtkm::cont::internal::Buffer>& buffers,
172  vtkm::cont::Token& token)
173  {
174  VTKM_ASSERT(buffers.size() == 1);
175  vtkm::Id numberOfBits = GetNumberOfValues(buffers);
176  VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
177 
178  return WritePortalType(
179  BitPortalType(buffers[0].WritePointerDevice(device, token), numberOfBits));
180  }
181 };
182 
183 } // end namespace internal
184 
185 
189 class ArrayHandleBitField : public ArrayHandle<bool, internal::StorageTagBitField>
190 {
191 public:
194 
195  VTKM_CONT
196  explicit ArrayHandleBitField(const vtkm::cont::BitField& bitField)
197  : Superclass(std::vector<vtkm::cont::internal::Buffer>(1, bitField.GetBuffer()))
198  {
199  }
200 };
201 
203  const vtkm::cont::BitField& bitField)
204 {
205  return ArrayHandleBitField{ bitField };
206 }
207 
209  vtkm::cont::BitField&& bitField) noexcept
210 {
211  return ArrayHandleBitField{ std::move(bitField) };
212 }
213 }
214 } // end namespace vtkm::cont
215 
216 #endif // vtk_m_cont_ArrayHandleBitField_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
ArrayHandle.h
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::Get
auto Get(const vtkm::Tuple< Ts... > &tuple)
Retrieve the object from a vtkm::Tuple at the given index.
Definition: Tuple.h:81
VTKM_ARRAY_HANDLE_SUBCLASS_NT
#define VTKM_ARRAY_HANDLE_SUBCLASS_NT(classname, superclass)
Macro to make default methods in ArrayHandle subclasses.
Definition: ArrayHandle.h:266
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::IdComponent
vtkm::Int32 IdComponent
Base type to use to index small lists.
Definition: Types.h:194
BitField.h
vtkm::WordTypeDefault
vtkm::UInt32 WordTypeDefault
The default word size used for atomic bitwise operations.
Definition: Types.h:198
Storage.h
vtkm::cont::ArrayHandleBitField::Superclass
vtkm::cont::detail::GetTypeInParentheses< void(ArrayHandle< bool, internal::StorageTagBitField >) >::type Superclass
Definition: ArrayHandleBitField.h:193
vtkm::cont::ArrayHandleBitField::ArrayHandleBitField
ArrayHandleBitField(const vtkm::cont::BitField &bitField)
Definition: ArrayHandleBitField.h:196
vtkm::BufferSizeType
vtkm::Int64 BufferSizeType
Definition: DeviceAdapterMemoryManager.h:27
vtkm::cont::GetSizeString
std::string GetSizeString(vtkm::UInt64 bytes, int prec=2)
Returns "%1 (%2 bytes)" where %1 is the result from GetHumanReadableSize and %2 is the exact number o...
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
VTKM_STATIC_ASSERT
#define VTKM_STATIC_ASSERT(condition)
Definition: StaticAssert.h:16
VTKM_LOG_F
#define VTKM_LOG_F(level,...)
Writes a message using printf syntax to the indicated log level.
Definition: Logging.h:209
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::LogLevel::MemCont
@ MemCont
Host-side resource allocations/frees (e.g. ArrayHandle control buffers).
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
vtkm::UInt8
uint8_t UInt8
Base type to use for 8-bit unsigned integer numbers.
Definition: Types.h:169
vtkm::cont::DeviceAdapterId
An object used to specify a device.
Definition: DeviceAdapterTag.h:58
vtkm::cont::BitField
Definition: BitField.h:497
vtkm::cont::ErrorBadValue
This class is thrown when a VTKm function or method encounters an invalid value that inhibits progres...
Definition: ErrorBadValue.h:25
vtkm::UInt64
unsigned long long UInt64
Base type to use for 64-bit signed integer numbers.
Definition: Types.h:207
vtkm::CopyFlag
CopyFlag
Identifier used to specify whether a function should deep copy data.
Definition: Flags.h:17
vtkm::cont::make_ArrayHandleBitField
vtkm::cont::ArrayHandleBitField make_ArrayHandleBitField(const vtkm::cont::BitField &bitField)
Definition: ArrayHandleBitField.h:202
VTKM_ALWAYS_EXPORT
#define VTKM_ALWAYS_EXPORT
Definition: ExportMacros.h:89
vtkm::cont::ArrayHandleBitField
The ArrayHandleBitField class is a boolean-valued ArrayHandle that is backed by a BitField.
Definition: ArrayHandleBitField.h:189