mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Store the number of bits of a BitField in the Buffer's metadata
The number of bits in a `BitField` cannot be directly implied from the size of the buffer (because the buffer gets padded to the nearest sized word). Thus, the `BitField stored the number of bits in its own internals. Unfortunately, that caused issues when passing the `BitField` data between it and an `ArrayHandleBitField`. If the `ArrayHandleBitField` resized itself, the `BitField` would not see the new size because it ignored the new buffer size. To get around this problem, `BitField` now declares its own `BufferMetaData` that stores the number of bits. Now, since the number of bits is stored in the `Buffer` object, it is sufficient to just share the `Buffer` to synchronize all of the state.
This commit is contained in:
parent
da0403be76
commit
4345fe26b0
@ -24,9 +24,7 @@ VTKM_CONT void ArrayHandleReleaseResourcesExecution(
|
|||||||
|
|
||||||
for (auto&& buf : buffers)
|
for (auto&& buf : buffers)
|
||||||
{
|
{
|
||||||
// Getting a write host buffer should invalidate any execution arrays.
|
buf.ReleaseDeviceResources();
|
||||||
// Might want to make something more explicit in Buffer.
|
|
||||||
buf.WritePointerHost(token);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,8 +74,6 @@ class Storage<bool, StorageTagBitField>
|
|||||||
using BitPortalType = vtkm::cont::detail::BitPortal;
|
using BitPortalType = vtkm::cont::detail::BitPortal;
|
||||||
using BitPortalConstType = vtkm::cont::detail::BitPortalConst;
|
using BitPortalConstType = vtkm::cont::detail::BitPortalConst;
|
||||||
|
|
||||||
vtkm::Id NumberOfBits;
|
|
||||||
|
|
||||||
using WordType = vtkm::WordTypeDefault;
|
using WordType = vtkm::WordTypeDefault;
|
||||||
static constexpr vtkm::Id BlockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
|
static constexpr vtkm::Id BlockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
|
||||||
VTKM_STATIC_ASSERT(BlockSize >= static_cast<vtkm::Id>(sizeof(WordType)));
|
VTKM_STATIC_ASSERT(BlockSize >= static_cast<vtkm::Id>(sizeof(WordType)));
|
||||||
@ -86,55 +84,53 @@ public:
|
|||||||
|
|
||||||
VTKM_CONT vtkm::IdComponent GetNumberOfBuffers() const { return 1; }
|
VTKM_CONT vtkm::IdComponent GetNumberOfBuffers() const { return 1; }
|
||||||
|
|
||||||
VTKM_CONT Storage()
|
VTKM_CONT Storage() {}
|
||||||
: NumberOfBits(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit VTKM_CONT Storage(vtkm::Id numberOfBits)
|
VTKM_CONT void ResizeBuffers(vtkm::Id numberOfBits,
|
||||||
: NumberOfBits(numberOfBits)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT void ResizeBuffers(vtkm::Id numValues,
|
|
||||||
vtkm::cont::internal::Buffer* buffers,
|
vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::CopyFlag preserve,
|
vtkm::CopyFlag preserve,
|
||||||
vtkm::cont::Token& token)
|
vtkm::cont::Token& token)
|
||||||
{
|
{
|
||||||
this->NumberOfBits = numValues;
|
const vtkm::Id bytesNeeded = (numberOfBits + CHAR_BIT - 1) / CHAR_BIT;
|
||||||
|
|
||||||
const vtkm::Id bytesNeeded = (this->NumberOfBits + CHAR_BIT - 1) / CHAR_BIT;
|
|
||||||
const vtkm::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
|
const vtkm::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
|
||||||
const vtkm::Id numBytes = blocksNeeded * BlockSize;
|
const vtkm::Id numBytes = blocksNeeded * BlockSize;
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
buffers[0].SetNumberOfBytes(numBytes, preserve, token);
|
buffers[0].SetNumberOfBytes(numBytes, preserve, token);
|
||||||
|
vtkm::cont::detail::GetBitFieldMetaData(buffers[0])->NumberOfBits = numberOfBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
|
VTKM_CONT vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
|
||||||
{
|
{
|
||||||
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= this->NumberOfBits);
|
vtkm::Id numberOfBits = vtkm::cont::detail::GetBitFieldMetaData(buffers[0])->NumberOfBits;
|
||||||
(void)buffers;
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
||||||
return this->NumberOfBits;
|
return numberOfBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::cont::DeviceAdapterId device,
|
vtkm::cont::DeviceAdapterId device,
|
||||||
vtkm::cont::Token& token)
|
vtkm::cont::Token& token)
|
||||||
{
|
{
|
||||||
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= this->NumberOfBits);
|
vtkm::Id numberOfBits = this->GetNumberOfValues(buffers);
|
||||||
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
||||||
|
|
||||||
return ReadPortalType(
|
return ReadPortalType(
|
||||||
BitPortalConstType(buffers[0].ReadPointerDevice(device, token), this->NumberOfBits));
|
BitPortalConstType(buffers[0].ReadPointerDevice(device, token), numberOfBits));
|
||||||
}
|
}
|
||||||
|
|
||||||
VTKM_CONT WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers,
|
VTKM_CONT WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers,
|
||||||
vtkm::cont::DeviceAdapterId device,
|
vtkm::cont::DeviceAdapterId device,
|
||||||
vtkm::cont::Token& token)
|
vtkm::cont::Token& token)
|
||||||
{
|
{
|
||||||
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= this->NumberOfBits);
|
vtkm::Id numberOfBits = this->GetNumberOfValues(buffers);
|
||||||
|
VTKM_ASSERT((buffers[0].GetNumberOfBytes() * CHAR_BIT) >= numberOfBits);
|
||||||
|
|
||||||
return WritePortalType(
|
return WritePortalType(
|
||||||
BitPortalType(buffers[0].WritePointerDevice(device, token), this->NumberOfBits));
|
BitPortalType(buffers[0].WritePointerDevice(device, token), numberOfBits));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,7 +219,7 @@ public:
|
|||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
explicit ArrayHandleBitField(const vtkm::cont::BitField& bitField)
|
explicit ArrayHandleBitField(const vtkm::cont::BitField& bitField)
|
||||||
: Superclass(bitField.GetData().GetBuffers(), StorageType(bitField.GetNumberOfBits()))
|
: Superclass(std::vector<vtkm::cont::internal::Buffer>(1, bitField.GetBuffer()))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
187
vtkm/cont/BitField.cxx
Normal file
187
vtkm/cont/BitField.cxx
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#include <vtkm/cont/BitField.h>
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct DeviceCheckFunctor
|
||||||
|
{
|
||||||
|
vtkm::cont::DeviceAdapterId FoundDevice = vtkm::cont::DeviceAdapterTagUndefined{};
|
||||||
|
|
||||||
|
VTKM_CONT void operator()(vtkm::cont::DeviceAdapterId device,
|
||||||
|
const vtkm::cont::internal::Buffer& buffer)
|
||||||
|
{
|
||||||
|
if (this->FoundDevice == vtkm::cont::DeviceAdapterTagUndefined{})
|
||||||
|
{
|
||||||
|
if (buffer.IsAllocatedOnDevice(device))
|
||||||
|
{
|
||||||
|
this->FoundDevice = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace cont
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
|
||||||
|
const vtkm::cont::internal::Buffer& buffer)
|
||||||
|
{
|
||||||
|
vtkm::cont::internal::BufferMetaData* generalMetaData = buffer.GetMetaData();
|
||||||
|
if (generalMetaData == nullptr)
|
||||||
|
{
|
||||||
|
VTKM_LOG_F(vtkm::cont::LogLevel::Warn, "BitField has buffer with no metadata. Setting.");
|
||||||
|
const_cast<vtkm::cont::internal::Buffer&>(buffer).SetMetaData(
|
||||||
|
vtkm::cont::internal::BitFieldMetaData{});
|
||||||
|
generalMetaData = buffer.GetMetaData();
|
||||||
|
VTKM_ASSERT(generalMetaData != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::internal::BitFieldMetaData* metadata =
|
||||||
|
dynamic_cast<vtkm::cont::internal::BitFieldMetaData*>(generalMetaData);
|
||||||
|
if (metadata == nullptr)
|
||||||
|
{
|
||||||
|
VTKM_LOG_F(vtkm::cont::LogLevel::Error,
|
||||||
|
"BitField has a buffer with metadata of the wrong type. "
|
||||||
|
"Replacing, but this will likely cause problems.");
|
||||||
|
const_cast<vtkm::cont::internal::Buffer&>(buffer).SetMetaData(
|
||||||
|
vtkm::cont::internal::BitFieldMetaData{});
|
||||||
|
generalMetaData = buffer.GetMetaData();
|
||||||
|
metadata = dynamic_cast<vtkm::cont::internal::BitFieldMetaData*>(generalMetaData);
|
||||||
|
VTKM_ASSERT(metadata != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to make sure that the buffer is at least as larger as needed for buffer size.
|
||||||
|
VTKM_ASSERT(buffer.GetNumberOfBytes() * CHAR_BIT >= metadata->NumberOfBits);
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
|
||||||
|
BitFieldMetaData::~BitFieldMetaData() {}
|
||||||
|
|
||||||
|
std::unique_ptr<vtkm::cont::internal::BufferMetaData> BitFieldMetaData::DeepCopy() const
|
||||||
|
{
|
||||||
|
return std::unique_ptr<vtkm::cont::internal::BufferMetaData>(new BitFieldMetaData(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
BitField::BitField()
|
||||||
|
{
|
||||||
|
this->Buffer.SetMetaData(internal::BitFieldMetaData{});
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::Id BitField::GetNumberOfBits() const
|
||||||
|
{
|
||||||
|
auto metadata = detail::GetBitFieldMetaData(this->Buffer);
|
||||||
|
return metadata->NumberOfBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitField::Allocate(vtkm::Id numberOfBits,
|
||||||
|
vtkm::CopyFlag preserve,
|
||||||
|
vtkm::cont::Token& token) const
|
||||||
|
{
|
||||||
|
const vtkm::BufferSizeType bytesNeeded = (numberOfBits + CHAR_BIT - 1) / CHAR_BIT;
|
||||||
|
const vtkm::BufferSizeType blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
|
||||||
|
const vtkm::BufferSizeType numBytes = blocksNeeded * BlockSize;
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
this->Buffer.SetNumberOfBytes(numBytes, preserve, token);
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits = numberOfBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitField::ReleaseResourcesExecution()
|
||||||
|
{
|
||||||
|
this->Buffer.ReleaseDeviceResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitField::ReleaseResources()
|
||||||
|
{
|
||||||
|
vtkm::cont::Token token;
|
||||||
|
this->Buffer.SetNumberOfBytes(0, vtkm::CopyFlag::Off, token);
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitField::SyncControlArray() const
|
||||||
|
{
|
||||||
|
vtkm::cont::Token token;
|
||||||
|
this->Buffer.ReadPointerHost(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BitField::IsOnDevice(vtkm::cont::DeviceAdapterId device) const
|
||||||
|
{
|
||||||
|
return this->Buffer.IsAllocatedOnDevice(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::DeviceAdapterId BitField::GetDeviceAdapterId() const
|
||||||
|
{
|
||||||
|
DeviceCheckFunctor functor;
|
||||||
|
vtkm::ListForEach(functor, VTKM_DEFAULT_DEVICE_ADAPTER_LIST{}, this->Buffer);
|
||||||
|
return functor.FoundDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
BitField::WritePortalType BitField::WritePortal() const
|
||||||
|
{
|
||||||
|
vtkm::cont::Token token;
|
||||||
|
return WritePortalType(this->Buffer.WritePointerHost(token),
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitField::ReadPortalType BitField::ReadPortal() const
|
||||||
|
{
|
||||||
|
vtkm::cont::Token token;
|
||||||
|
return ReadPortalType(this->Buffer.ReadPointerHost(token),
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitField::ReadPortalType BitField::PrepareForInput(vtkm::cont::DeviceAdapterId device,
|
||||||
|
vtkm::cont::Token& token) const
|
||||||
|
{
|
||||||
|
return ReadPortalType(this->Buffer.ReadPointerDevice(device, token),
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitField::WritePortalType BitField::PrepareForOutput(vtkm::Id numBits,
|
||||||
|
vtkm::cont::DeviceAdapterId device,
|
||||||
|
vtkm::cont::Token& token) const
|
||||||
|
{
|
||||||
|
this->Allocate(numBits, vtkm::CopyFlag::Off, token);
|
||||||
|
return WritePortalType(this->Buffer.WritePointerDevice(device, token),
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
BitField::WritePortalType BitField::PrepareForInPlace(vtkm::cont::DeviceAdapterId device,
|
||||||
|
vtkm::cont::Token& token) const
|
||||||
|
{
|
||||||
|
return WritePortalType(this->Buffer.WritePointerDevice(device, token),
|
||||||
|
detail::GetBitFieldMetaData(this->Buffer)->NumberOfBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace vtkm::cont
|
@ -12,7 +12,7 @@
|
|||||||
#define vtk_m_cont_BitField_h
|
#define vtk_m_cont_BitField_h
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayHandle.h>
|
#include <vtkm/cont/ArrayHandle.h>
|
||||||
#include <vtkm/cont/Logging.h>
|
#include <vtkm/cont/vtkm_cont_export.h>
|
||||||
|
|
||||||
#include <vtkm/Atomic.h>
|
#include <vtkm/Atomic.h>
|
||||||
#include <vtkm/Deprecated.h>
|
#include <vtkm/Deprecated.h>
|
||||||
@ -33,7 +33,18 @@ class BitField;
|
|||||||
|
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
struct StorageTagBitField;
|
struct StorageTagBitField;
|
||||||
|
|
||||||
|
struct VTKM_CONT_EXPORT BitFieldMetaData : vtkm::cont::internal::BufferMetaData
|
||||||
|
{
|
||||||
|
vtkm::Id NumberOfBits = 0;
|
||||||
|
|
||||||
|
VTKM_CONT ~BitFieldMetaData() override;
|
||||||
|
|
||||||
|
VTKM_CONT std::unique_ptr<vtkm::cont::internal::BufferMetaData> DeepCopy() const override;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
@ -88,6 +99,9 @@ struct BitCoordinate
|
|||||||
vtkm::Int32 BitOffset; // [0, bitsInWord)
|
vtkm::Int32 BitOffset; // [0, bitsInWord)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VTKM_CONT_EXPORT vtkm::cont::internal::BitFieldMetaData* GetBitFieldMetaData(
|
||||||
|
const vtkm::cont::internal::Buffer& buffer);
|
||||||
|
|
||||||
/// Portal for performing bit or word operations on a BitField.
|
/// Portal for performing bit or word operations on a BitField.
|
||||||
///
|
///
|
||||||
/// This is the implementation used by BitPortal and BitPortalConst.
|
/// This is the implementation used by BitPortal and BitPortalConst.
|
||||||
@ -131,18 +145,6 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class vtkm::cont::BitField;
|
friend class vtkm::cont::BitField;
|
||||||
|
|
||||||
/// Construct a BitPortal from an ArrayHandle with basic storage's portal.
|
|
||||||
template <typename PortalType>
|
|
||||||
VTKM_EXEC_CONT BitPortalBase(const PortalType& portal, vtkm::Id numberOfBits)
|
|
||||||
: Data{ portal.GetIteratorBegin() }
|
|
||||||
, NumberOfBits{ numberOfBits }
|
|
||||||
{
|
|
||||||
VTKM_STATIC_ASSERT_MSG(HasPointerAccess<PortalType>::value,
|
|
||||||
"Source portal must return a pointer from "
|
|
||||||
"GetIteratorBegin().");
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class vtkm::cont::internal::Storage<bool, vtkm::cont::internal::StorageTagBitField>;
|
friend class vtkm::cont::internal::Storage<bool, vtkm::cont::internal::StorageTagBitField>;
|
||||||
|
|
||||||
/// Construct a BitPortal from a raw array.
|
/// Construct a BitPortal from a raw array.
|
||||||
@ -513,13 +515,14 @@ struct IsValidWordTypeDeprecated<WordType, void>
|
|||||||
|
|
||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
|
|
||||||
class BitField
|
class VTKM_CONT_EXPORT BitField
|
||||||
{
|
{
|
||||||
static constexpr vtkm::Id BlockSize = detail::BitFieldTraits::BlockSize;
|
static constexpr vtkm::Id BlockSize = detail::BitFieldTraits::BlockSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The type array handle used to store the bit data internally:
|
/// The type array handle used to store the bit data internally:
|
||||||
using ArrayHandleType = ArrayHandle<WordTypeDefault, StorageTagBasic>;
|
using ArrayHandleType VTKM_DEPRECATED(1.6, "BitField now uses a Buffer to store data.") =
|
||||||
|
ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>;
|
||||||
|
|
||||||
/// The BitPortal used in the control environment.
|
/// The BitPortal used in the control environment.
|
||||||
using WritePortalType = detail::BitPortal;
|
using WritePortalType = detail::BitPortal;
|
||||||
@ -559,10 +562,7 @@ public:
|
|||||||
using IsValidWordTypeAtomicControl VTKM_DEPRECATED(1.6, "Use IsValidWordTypeAtomic instead.") =
|
using IsValidWordTypeAtomicControl VTKM_DEPRECATED(1.6, "Use IsValidWordTypeAtomic instead.") =
|
||||||
detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
|
detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
|
||||||
|
|
||||||
VTKM_CONT BitField()
|
VTKM_CONT BitField();
|
||||||
: Internals{ std::make_shared<InternalStruct>() }
|
|
||||||
{
|
|
||||||
}
|
|
||||||
VTKM_CONT BitField(const BitField&) = default;
|
VTKM_CONT BitField(const BitField&) = default;
|
||||||
VTKM_CONT BitField(BitField&&) noexcept = default;
|
VTKM_CONT BitField(BitField&&) noexcept = default;
|
||||||
VTKM_CONT ~BitField() = default;
|
VTKM_CONT ~BitField() = default;
|
||||||
@ -570,22 +570,23 @@ public:
|
|||||||
VTKM_CONT BitField& operator=(BitField&&) noexcept = default;
|
VTKM_CONT BitField& operator=(BitField&&) noexcept = default;
|
||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
bool operator==(const BitField& rhs) const { return this->Internals == rhs.Internals; }
|
bool operator==(const BitField& rhs) const { return this->Buffer == rhs.Buffer; }
|
||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
bool operator!=(const BitField& rhs) const { return this->Internals != rhs.Internals; }
|
bool operator!=(const BitField& rhs) const { return this->Buffer != rhs.Buffer; }
|
||||||
|
|
||||||
|
/// Return the internal `Buffer` used to store the `BitField`.
|
||||||
|
VTKM_CONT vtkm::cont::internal::Buffer GetBuffer() const { return this->Buffer; }
|
||||||
|
|
||||||
/// Return the internal ArrayHandle used to store the BitField.
|
/// Return the internal ArrayHandle used to store the BitField.
|
||||||
VTKM_CONT
|
VTKM_CONT VTKM_DEPRECATED(1.6, "BitField now uses a Buffer to store data.")
|
||||||
ArrayHandleType& GetData() { return this->Internals->Data; }
|
ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic> GetData() const
|
||||||
|
{
|
||||||
/// Return the internal ArrayHandle used to store the BitField.
|
return vtkm::cont::ArrayHandle<vtkm::WordTypeDefault, StorageTagBasic>(&this->Buffer);
|
||||||
VTKM_CONT
|
}
|
||||||
const ArrayHandleType& GetData() const { return this->Internals->Data; }
|
|
||||||
|
|
||||||
/// Return the number of bits stored by this BitField.
|
/// Return the number of bits stored by this BitField.
|
||||||
VTKM_CONT
|
VTKM_CONT vtkm::Id GetNumberOfBits() const;
|
||||||
vtkm::Id GetNumberOfBits() const { return this->Internals->NumberOfBits; }
|
|
||||||
|
|
||||||
/// Return the number of words (of @a WordType) stored in this bit fields.
|
/// Return the number of words (of @a WordType) stored in this bit fields.
|
||||||
///
|
///
|
||||||
@ -594,83 +595,69 @@ public:
|
|||||||
{
|
{
|
||||||
VTKM_STATIC_ASSERT(IsValidWordType<WordType>::value);
|
VTKM_STATIC_ASSERT(IsValidWordType<WordType>::value);
|
||||||
static constexpr vtkm::Id WordBits = static_cast<vtkm::Id>(sizeof(WordType) * CHAR_BIT);
|
static constexpr vtkm::Id WordBits = static_cast<vtkm::Id>(sizeof(WordType) * CHAR_BIT);
|
||||||
return (this->Internals->NumberOfBits + WordBits - 1) / WordBits;
|
return (this->GetNumberOfBits() + WordBits - 1) / WordBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate the requested number of bits.
|
/// Allocate the requested number of bits.
|
||||||
VTKM_CONT
|
VTKM_CONT void Allocate(vtkm::Id numberOfBits,
|
||||||
void Allocate(vtkm::Id numberOfBits)
|
vtkm::CopyFlag preserve,
|
||||||
|
vtkm::cont::Token& token) const;
|
||||||
|
|
||||||
|
/// Allocate the requested number of bits.
|
||||||
|
VTKM_CONT void Allocate(vtkm::Id numberOfBits,
|
||||||
|
vtkm::CopyFlag preserve = vtkm::CopyFlag::Off) const
|
||||||
{
|
{
|
||||||
const vtkm::Id numWords = this->BitsToAllocatedStorageWords(numberOfBits);
|
vtkm::cont::Token token;
|
||||||
|
this->Allocate(numberOfBits, preserve, token);
|
||||||
VTKM_LOG_F(vtkm::cont::LogLevel::MemCont,
|
|
||||||
"BitField Allocation: %llu bits, blocked up to %s.",
|
|
||||||
static_cast<unsigned long long>(numberOfBits),
|
|
||||||
vtkm::cont::GetSizeString(
|
|
||||||
static_cast<vtkm::UInt64>(static_cast<size_t>(numWords) * sizeof(WordTypeDefault)))
|
|
||||||
.c_str());
|
|
||||||
|
|
||||||
this->Internals->Data.Allocate(numWords);
|
|
||||||
this->Internals->NumberOfBits = numberOfBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shrink the bit field to the requested number of bits.
|
/// Shrink the bit field to the requested number of bits.
|
||||||
VTKM_CONT
|
VTKM_CONT VTKM_DEPRECATED(1.6,
|
||||||
void Shrink(vtkm::Id numberOfBits)
|
"Use Allocate with preserve = On.") void Shrink(vtkm::Id numberOfBits)
|
||||||
{
|
{
|
||||||
const vtkm::Id numWords = this->BitsToAllocatedStorageWords(numberOfBits);
|
this->Allocate(numberOfBits, vtkm::CopyFlag::On);
|
||||||
this->Internals->Data.Shrink(numWords);
|
|
||||||
this->Internals->NumberOfBits = numberOfBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Release all execution-side resources held by this BitField.
|
/// Release all execution-side resources held by this BitField.
|
||||||
VTKM_CONT
|
VTKM_CONT void ReleaseResourcesExecution();
|
||||||
void ReleaseResourcesExecution() { this->Internals->Data.ReleaseResourcesExecution(); }
|
|
||||||
|
|
||||||
/// Release all resources held by this BitField and reset to empty.
|
/// Release all resources held by this BitField and reset to empty.
|
||||||
VTKM_CONT
|
VTKM_CONT void ReleaseResources();
|
||||||
void ReleaseResources()
|
|
||||||
{
|
|
||||||
this->Internals->Data.ReleaseResources();
|
|
||||||
this->Internals->NumberOfBits = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Force the control array to sync with the last-used device.
|
/// Force the control array to sync with the last-used device.
|
||||||
VTKM_CONT
|
VTKM_CONT void SyncControlArray() const;
|
||||||
void SyncControlArray() const { this->Internals->Data.SyncControlArray(); }
|
|
||||||
|
|
||||||
/// The id of the device where the most up-to-date copy of the data is
|
/// Returns true if the `BitField`'s data is on the given device. If the data are on the given
|
||||||
/// currently resident. If the data is on the host, DeviceAdapterTagUndefined
|
/// device, then preparing for that device should not require any data movement.
|
||||||
/// is returned.
|
///
|
||||||
VTKM_CONT
|
VTKM_CONT bool IsOnDevice(vtkm::cont::DeviceAdapterId device) const;
|
||||||
DeviceAdapterId GetDeviceAdapterId() const { return this->Internals->Data.GetDeviceAdapterId(); }
|
|
||||||
|
/// Returns true if the `BitField`'s data is on the host. If the data are on the given
|
||||||
|
/// device, then calling `ReadPortal` or `WritePortal` should not require any data movement.
|
||||||
|
///
|
||||||
|
VTKM_CONT bool IsOnHost() const
|
||||||
|
{
|
||||||
|
return this->IsOnDevice(vtkm::cont::DeviceAdapterTagUndefined{});
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT VTKM_DEPRECATED(1.6, "Data can be on multiple devices. Use IsOnDevice.")
|
||||||
|
vtkm::cont::DeviceAdapterId GetDeviceAdapterId() const;
|
||||||
|
|
||||||
/// \brief Get a portal to the data that is usable from the control environment.
|
/// \brief Get a portal to the data that is usable from the control environment.
|
||||||
///
|
///
|
||||||
/// As long as this portal is in scope, no one else will be able to read or write the BitField.
|
/// As long as this portal is in scope, no one else will be able to read or write the BitField.
|
||||||
VTKM_CONT WritePortalType WritePortal() const
|
VTKM_CONT WritePortalType WritePortal() const;
|
||||||
{
|
|
||||||
auto dataPortal = this->Internals->Data.WritePortal();
|
|
||||||
return WritePortalType{ dataPortal, this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Get a read-only portal to the data that is usable from the control environment.
|
/// \brief Get a read-only portal to the data that is usable from the control environment.
|
||||||
///
|
///
|
||||||
/// As long as this portal is in scope, no one else will be able to write in the BitField.
|
/// As long as this portal is in scope, no one else will be able to write in the BitField.
|
||||||
VTKM_CONT ReadPortalType ReadPortal() const
|
VTKM_CONT ReadPortalType ReadPortal() const;
|
||||||
{
|
|
||||||
auto dataPortal = this->Internals->Data.ReadPortal();
|
|
||||||
return ReadPortalType{ dataPortal, this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT
|
VTKM_CONT
|
||||||
VTKM_DEPRECATED(1.6,
|
VTKM_DEPRECATED(1.6,
|
||||||
"Use BitField::WritePortal() instead. "
|
"Use BitField::WritePortal() instead. "
|
||||||
"Note that the returned portal will lock the array while it is in scope.")
|
"Note that the returned portal will lock the array while it is in scope.")
|
||||||
detail::BitPortal GetPortalControl()
|
detail::BitPortal GetPortalControl() { return this->WritePortal(); }
|
||||||
{
|
|
||||||
return detail::BitPortal{ this->Internals->Data.WritePortal(), this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a read-only portal to the data that is usable from the control
|
/// Get a read-only portal to the data that is usable from the control
|
||||||
/// environment.
|
/// environment.
|
||||||
@ -678,26 +665,15 @@ public:
|
|||||||
VTKM_DEPRECATED(1.6,
|
VTKM_DEPRECATED(1.6,
|
||||||
"Use BitField::ReadPortal() instead. "
|
"Use BitField::ReadPortal() instead. "
|
||||||
"Note that the returned portal will lock the array while it is in scope.")
|
"Note that the returned portal will lock the array while it is in scope.")
|
||||||
detail::BitPortalConst GetPortalConstControl() const
|
detail::BitPortalConst GetPortalConstControl() const { return this->ReadPortal(); }
|
||||||
{
|
|
||||||
return detail::BitPortalConst{ this->Internals->Data.ReadPortal(),
|
|
||||||
this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prepares this BitField to be used as an input to an operation in the
|
/// Prepares this BitField to be used as an input to an operation in the
|
||||||
/// execution environment. If necessary, copies data to the execution
|
/// execution environment. If necessary, copies data to the execution
|
||||||
/// environment. Can throw an exception if this BitField does not yet contain
|
/// environment. Can throw an exception if this BitField does not yet contain
|
||||||
/// any data. Returns a portal that can be used in code running in the
|
/// any data. Returns a portal that can be used in code running in the
|
||||||
/// execution environment.
|
/// execution environment.
|
||||||
template <typename DeviceAdapterTag>
|
VTKM_CONT ReadPortalType PrepareForInput(vtkm::cont::DeviceAdapterId device,
|
||||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(
|
vtkm::cont::Token& token) const;
|
||||||
DeviceAdapterTag device,
|
|
||||||
vtkm::cont::Token& token) const
|
|
||||||
{
|
|
||||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::PortalConst;
|
|
||||||
return PortalType{ this->Internals->Data.PrepareForInput(device, token),
|
|
||||||
this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename DeviceAdapterTag>
|
template <typename DeviceAdapterTag>
|
||||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInput now requires a vtkm::cont::Token object.")
|
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInput now requires a vtkm::cont::Token object.")
|
||||||
@ -714,24 +690,9 @@ public:
|
|||||||
/// that the array will be filled soon (i.e. before any other methods of this
|
/// that the array will be filled soon (i.e. before any other methods of this
|
||||||
/// object are called). Returns a portal that can be used in code running in
|
/// object are called). Returns a portal that can be used in code running in
|
||||||
/// the execution environment.
|
/// the execution environment.
|
||||||
template <typename DeviceAdapterTag>
|
VTKM_CONT WritePortalType PrepareForOutput(vtkm::Id numBits,
|
||||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal
|
vtkm::cont::DeviceAdapterId device,
|
||||||
PrepareForOutput(vtkm::Id numBits, DeviceAdapterTag device, vtkm::cont::Token& token) const
|
vtkm::cont::Token& token) const;
|
||||||
{
|
|
||||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::Portal;
|
|
||||||
const vtkm::Id numWords = this->BitsToAllocatedStorageWords(numBits);
|
|
||||||
|
|
||||||
VTKM_LOG_F(vtkm::cont::LogLevel::MemExec,
|
|
||||||
"BitField Allocation: %llu bits, blocked up to %s.",
|
|
||||||
static_cast<unsigned long long>(numBits),
|
|
||||||
vtkm::cont::GetSizeString(
|
|
||||||
static_cast<vtkm::UInt64>(static_cast<size_t>(numWords) * sizeof(WordTypeDefault)))
|
|
||||||
.c_str());
|
|
||||||
|
|
||||||
auto portal = this->Internals->Data.PrepareForOutput(numWords, device, token);
|
|
||||||
this->Internals->NumberOfBits = numBits;
|
|
||||||
return PortalType{ portal, numBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename DeviceAdapterTag>
|
template <typename DeviceAdapterTag>
|
||||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForOutput now requires a vtkm::cont::Token object.")
|
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForOutput now requires a vtkm::cont::Token object.")
|
||||||
@ -747,15 +708,8 @@ public:
|
|||||||
/// the execution environment. Can throw an exception if this BitField does
|
/// the execution environment. Can throw an exception if this BitField does
|
||||||
/// not yet contain any data. Returns a portal that can be used in code
|
/// not yet contain any data. Returns a portal that can be used in code
|
||||||
/// running in the execution environment.
|
/// running in the execution environment.
|
||||||
template <typename DeviceAdapterTag>
|
VTKM_CONT WritePortalType PrepareForInPlace(vtkm::cont::DeviceAdapterId device,
|
||||||
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(
|
vtkm::cont::Token& token) const;
|
||||||
DeviceAdapterTag device,
|
|
||||||
vtkm::cont::Token& token) const
|
|
||||||
{
|
|
||||||
using PortalType = typename ExecutionTypes<DeviceAdapterTag>::Portal;
|
|
||||||
return PortalType{ this->Internals->Data.PrepareForInPlace(device, token),
|
|
||||||
this->Internals->NumberOfBits };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename DeviceAdapterTag>
|
template <typename DeviceAdapterTag>
|
||||||
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInPlace now requires a vtkm::cont::Token object.")
|
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInPlace now requires a vtkm::cont::Token object.")
|
||||||
@ -767,27 +721,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Returns the number of words, padded out to respect BlockSize.
|
mutable vtkm::cont::internal::Buffer Buffer;
|
||||||
VTKM_CONT
|
|
||||||
static vtkm::Id BitsToAllocatedStorageWords(vtkm::Id numBits)
|
|
||||||
{
|
|
||||||
static constexpr vtkm::Id InternalWordSize = static_cast<vtkm::Id>(sizeof(WordTypeDefault));
|
|
||||||
|
|
||||||
// Round up to BlockSize bytes:
|
|
||||||
const vtkm::Id bytesNeeded = (numBits + CHAR_BIT - 1) / CHAR_BIT;
|
|
||||||
const vtkm::Id blocksNeeded = (bytesNeeded + BlockSize - 1) / BlockSize;
|
|
||||||
const vtkm::Id numBytes = blocksNeeded * BlockSize;
|
|
||||||
const vtkm::Id numWords = numBytes / InternalWordSize;
|
|
||||||
return numWords;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VTKM_ALWAYS_EXPORT InternalStruct
|
|
||||||
{
|
|
||||||
ArrayHandleType Data;
|
|
||||||
vtkm::Id NumberOfBits;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<InternalStruct> Internals;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // end namespace vtkm::cont
|
} // end namespace vtkm::cont
|
||||||
|
@ -139,6 +139,7 @@ set(sources
|
|||||||
ArrayHandle.cxx
|
ArrayHandle.cxx
|
||||||
ArrayHandleBasic.cxx
|
ArrayHandleBasic.cxx
|
||||||
ArrayHandleSOA.cxx
|
ArrayHandleSOA.cxx
|
||||||
|
BitField.cxx
|
||||||
ColorTablePresets.cxx
|
ColorTablePresets.cxx
|
||||||
DeviceAdapterTag.cxx
|
DeviceAdapterTag.cxx
|
||||||
EnvironmentTracker.cxx
|
EnvironmentTracker.cxx
|
||||||
|
@ -545,7 +545,7 @@ Buffer::Buffer(const Buffer& src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Defined to prevent issues with CUDA
|
// Defined to prevent issues with CUDA
|
||||||
Buffer::Buffer(Buffer&& src)
|
Buffer::Buffer(Buffer&& src) noexcept
|
||||||
: Internals(std::move(src.Internals))
|
: Internals(std::move(src.Internals))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -561,7 +561,7 @@ Buffer& Buffer::operator=(const Buffer& src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Defined to prevent issues with CUDA
|
// Defined to prevent issues with CUDA
|
||||||
Buffer& Buffer::operator=(Buffer&& src)
|
Buffer& Buffer::operator=(Buffer&& src) noexcept
|
||||||
{
|
{
|
||||||
this->Internals = std::move(src.Internals);
|
this->Internals = std::move(src.Internals);
|
||||||
return *this;
|
return *this;
|
||||||
@ -816,6 +816,15 @@ void Buffer::Reset(const vtkm::cont::internal::BufferInfo& bufferInfo)
|
|||||||
this->Internals->SetNumberOfBytes(lock, bufferInfo.GetSize());
|
this->Internals->SetNumberOfBytes(lock, bufferInfo.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Buffer::ReleaseDeviceResources() const
|
||||||
|
{
|
||||||
|
vtkm::cont::Token token;
|
||||||
|
|
||||||
|
// Getting a write host buffer will invalidate any device arrays and preserve data
|
||||||
|
// on the host (copying if necessary).
|
||||||
|
this->WritePointerHost(token);
|
||||||
|
}
|
||||||
|
|
||||||
vtkm::cont::internal::BufferInfo Buffer::GetHostBufferInfo() const
|
vtkm::cont::internal::BufferInfo Buffer::GetHostBufferInfo() const
|
||||||
{
|
{
|
||||||
LockType lock = this->Internals->GetLock();
|
LockType lock = this->Internals->GetLock();
|
||||||
|
@ -76,12 +76,12 @@ public:
|
|||||||
VTKM_CONT Buffer();
|
VTKM_CONT Buffer();
|
||||||
|
|
||||||
VTKM_CONT Buffer(const Buffer& src);
|
VTKM_CONT Buffer(const Buffer& src);
|
||||||
VTKM_CONT Buffer(Buffer&& src);
|
VTKM_CONT Buffer(Buffer&& src) noexcept;
|
||||||
|
|
||||||
VTKM_CONT ~Buffer();
|
VTKM_CONT ~Buffer();
|
||||||
|
|
||||||
VTKM_CONT Buffer& operator=(const Buffer& src);
|
VTKM_CONT Buffer& operator=(const Buffer& src);
|
||||||
VTKM_CONT Buffer& operator=(Buffer&& src);
|
VTKM_CONT Buffer& operator=(Buffer&& src) noexcept;
|
||||||
|
|
||||||
/// \brief Returns the number of bytes held by the buffer.
|
/// \brief Returns the number of bytes held by the buffer.
|
||||||
///
|
///
|
||||||
@ -222,6 +222,18 @@ public:
|
|||||||
///
|
///
|
||||||
VTKM_CONT void Reset(const vtkm::cont::internal::BufferInfo& buffer);
|
VTKM_CONT void Reset(const vtkm::cont::internal::BufferInfo& buffer);
|
||||||
|
|
||||||
|
/// \brief Unallocates the buffer from all devices.
|
||||||
|
///
|
||||||
|
/// This method preserves the data on the host even if the data must be transferred
|
||||||
|
/// there.
|
||||||
|
///
|
||||||
|
/// Note that this method will not physically deallocate memory on a device that shares
|
||||||
|
/// a memory space with the host (since the data must be preserved on the host). This
|
||||||
|
/// is true even for memory spaces that page data between host and device. This method
|
||||||
|
/// will not attempt to unpage data from a device with shared memory.
|
||||||
|
///
|
||||||
|
VTKM_CONT void ReleaseDeviceResources() const;
|
||||||
|
|
||||||
/// \brief Gets the `BufferInfo` object to the memory allocated on the host.
|
/// \brief Gets the `BufferInfo` object to the memory allocated on the host.
|
||||||
///
|
///
|
||||||
VTKM_CONT vtkm::cont::internal::BufferInfo GetHostBufferInfo() const;
|
VTKM_CONT vtkm::cont::internal::BufferInfo GetHostBufferInfo() const;
|
||||||
|
@ -321,7 +321,7 @@ public:
|
|||||||
|
|
||||||
if (numBits == 0)
|
if (numBits == 0)
|
||||||
{
|
{
|
||||||
bits.Shrink(0);
|
bits.Allocate(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ public:
|
|||||||
|
|
||||||
if (numBits == 0)
|
if (numBits == 0)
|
||||||
{
|
{
|
||||||
bits.Shrink(0);
|
bits.Allocate(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,8 +150,7 @@ struct TestingBitField
|
|||||||
|
|
||||||
// NumBits should be rounded up to the nearest block of bytes, as defined in
|
// NumBits should be rounded up to the nearest block of bytes, as defined in
|
||||||
// the traits:
|
// the traits:
|
||||||
const vtkm::Id bytesInFieldData =
|
const vtkm::Id bytesInFieldData = field.GetBuffer().GetNumberOfBytes();
|
||||||
field.GetData().GetNumberOfValues() * static_cast<vtkm::Id>(sizeof(vtkm::WordTypeDefault));
|
|
||||||
|
|
||||||
const vtkm::Id blockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
|
const vtkm::Id blockSize = vtkm::cont::detail::BitFieldTraits::BlockSize;
|
||||||
const vtkm::Id numBytes = (NUM_BITS + CHAR_BIT - 1) / CHAR_BIT;
|
const vtkm::Id numBytes = (NUM_BITS + CHAR_BIT - 1) / CHAR_BIT;
|
||||||
|
Loading…
Reference in New Issue
Block a user