mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 02:25:42 +00:00
Add ability to fill values in a Buffer
This is in preparation to add a method to `ArrayHandle` that allows initializing fill values.
This commit is contained in:
parent
2eabba3366
commit
0cf996f410
@ -163,7 +163,6 @@ set(sources
|
||||
ErrorBadType.cxx
|
||||
FieldRangeCompute.cxx
|
||||
FieldRangeGlobalCompute.cxx
|
||||
internal/Buffer.cxx
|
||||
internal/DeviceAdapterMemoryManager.cxx
|
||||
internal/DeviceAdapterMemoryManagerShared.cxx
|
||||
internal/RuntimeDeviceConfiguration.cxx
|
||||
@ -193,6 +192,7 @@ set(device_sources
|
||||
ColorTable.cxx
|
||||
ConvertNumComponentsToOffsets.cxx
|
||||
Field.cxx
|
||||
internal/Buffer.cxx
|
||||
MergePartitionedDataSet.cxx
|
||||
PointLocatorSparseGrid.cxx
|
||||
RuntimeDeviceInformation.cxx
|
||||
|
@ -10,14 +10,18 @@
|
||||
|
||||
#include <vtkm/internal/Assume.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
#include <vtkm/cont/ErrorBadAllocation.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/cont/ErrorBadType.h>
|
||||
#include <vtkm/cont/RuntimeDeviceInformation.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
|
||||
#include <vtkm/cont/internal/Buffer.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterMemoryManager.h>
|
||||
|
||||
#include <vtkm/exec/FunctorBase.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstring>
|
||||
#include <deque>
|
||||
@ -157,6 +161,75 @@ struct MetaDataManager
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct FillFunctor : vtkm::exec::FunctorBase
|
||||
{
|
||||
T* TargetArray;
|
||||
const T* SourceValues;
|
||||
vtkm::Id NumSourceValues;
|
||||
|
||||
VTKM_CONT FillFunctor(void* targetArray,
|
||||
const void* sourceValues,
|
||||
vtkm::BufferSizeType sourceValuesSize,
|
||||
vtkm::BufferSizeType start)
|
||||
: TargetArray(reinterpret_cast<T*>(targetArray))
|
||||
, SourceValues(reinterpret_cast<const T*>(sourceValues))
|
||||
, NumSourceValues(sourceValuesSize / sizeof(T))
|
||||
{
|
||||
VTKM_ASSERT((sourceValuesSize % sizeof(T)) == 0);
|
||||
this->TargetArray += start / sizeof(T);
|
||||
}
|
||||
|
||||
VTKM_EXEC void operator()(vtkm::Id index) const
|
||||
{
|
||||
T* target = this->TargetArray + (index * this->NumSourceValues);
|
||||
for (vtkm::Id sourceIndex = 0; sourceIndex < this->NumSourceValues; ++sourceIndex)
|
||||
{
|
||||
*target = this->SourceValues[sourceIndex];
|
||||
++target;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Device>
|
||||
void FillBuffer(const vtkm::cont::internal::Buffer& target,
|
||||
const vtkm::cont::internal::Buffer& source,
|
||||
vtkm::BufferSizeType start,
|
||||
Device device,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
void* targetPointer = target.WritePointerDevice(device, token);
|
||||
const void* sourcePointer = source.ReadPointerDevice(device, token);
|
||||
|
||||
// Get after target locked with token.
|
||||
vtkm::BufferSizeType targetSize = target.GetNumberOfBytes();
|
||||
vtkm::BufferSizeType sourceSize = source.GetNumberOfBytes();
|
||||
if (targetSize <= start)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VTKM_ASSERT((targetSize % sourceSize) == 0);
|
||||
VTKM_ASSERT((start % sourceSize) == 0);
|
||||
|
||||
vtkm::Id numSources = (targetSize - start) / sourceSize;
|
||||
|
||||
if ((sourceSize >= 8) && ((sourceSize % 8) == 0))
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(
|
||||
FillFunctor<vtkm::UInt64>{ targetPointer, sourcePointer, sourceSize, start }, numSources);
|
||||
}
|
||||
else if ((sourceSize >= 4) && ((sourceSize % 4) == 0))
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(
|
||||
FillFunctor<vtkm::UInt32>{ targetPointer, sourcePointer, sourceSize, start }, numSources);
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Schedule(
|
||||
FillFunctor<vtkm::UInt8>{ targetPointer, sourcePointer, sourceSize, start }, numSources);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
@ -1017,6 +1090,44 @@ vtkm::cont::internal::BufferInfo Buffer::GetDeviceBufferInfo(
|
||||
throw vtkm::cont::ErrorBadDevice("Called Buffer::GetDeviceBufferInfo with invalid device");
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::Fill(const void* source,
|
||||
vtkm::BufferSizeType sourceSize,
|
||||
vtkm::BufferSizeType start,
|
||||
vtkm::cont::Token& token) const
|
||||
{
|
||||
vtkm::cont::internal::Buffer sourceBuffer;
|
||||
sourceBuffer.Reset(vtkm::cont::internal::BufferInfo(
|
||||
vtkm::cont::DeviceAdapterTagUndefined{},
|
||||
const_cast<void*>(source),
|
||||
const_cast<void*>(source),
|
||||
sourceSize,
|
||||
[](void*) {},
|
||||
[](void*&, void*&, vtkm::BufferSizeType, vtkm::BufferSizeType) {}));
|
||||
|
||||
// First, try setting on any device that already has the data.
|
||||
bool success = vtkm::cont::TryExecute([&](auto device) {
|
||||
if (this->IsAllocatedOnDevice(device))
|
||||
{
|
||||
FillBuffer(*this, sourceBuffer, start, device, token);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!success)
|
||||
{
|
||||
// Likely the data was not on any device. Fill on any device.
|
||||
vtkm::cont::TryExecute([&](auto device) {
|
||||
FillBuffer(*this, sourceBuffer, start, device, token);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
@ -310,6 +310,20 @@ public:
|
||||
VTKM_CONT vtkm::cont::internal::TransferredBuffer TakeDeviceBufferOwnership(
|
||||
vtkm::cont::DeviceAdapterId device);
|
||||
|
||||
/// \brief Fill up the buffer with particular values.
|
||||
///
|
||||
/// Given a short `source` C array (defined on the host), sets all values in the buffer
|
||||
/// to that source. The `sourceSize`, in bytes, is also specified. You also specify an
|
||||
/// offset to where the fill should `start`. Values before the `start` are not affected.
|
||||
///
|
||||
/// Both the size of the buffer (i.e. `GetNumberOfBytes`) and the `start` must be
|
||||
/// divisible by `sourceSize`.
|
||||
///
|
||||
VTKM_CONT void Fill(const void* source,
|
||||
vtkm::BufferSizeType sourceSize,
|
||||
vtkm::BufferSizeType start,
|
||||
vtkm::cont::Token& token) const;
|
||||
|
||||
VTKM_CONT bool operator==(const vtkm::cont::internal::Buffer& rhs) const
|
||||
{
|
||||
return (this->Internals == rhs.Internals);
|
||||
|
@ -186,6 +186,20 @@ void DoTest()
|
||||
VTKM_TEST_ASSERT(buffer.IsAllocatedOnHost());
|
||||
VTKM_TEST_ASSERT(!buffer.IsAllocatedOnDevice(device));
|
||||
|
||||
std::cout << "Fill end of buffer" << std::endl;
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
T fillValue = 1.234f;
|
||||
buffer.Fill(
|
||||
&fillValue, static_cast<vtkm::BufferSizeType>(sizeof(fillValue)), BUFFER_SIZE / 2, token);
|
||||
CheckPortal(MakePortal(buffer.ReadPointerHost(token), ARRAY_SIZE / 2));
|
||||
const T* array = reinterpret_cast<const T*>(buffer.ReadPointerHost(token));
|
||||
for (vtkm::Id index = (ARRAY_SIZE / 2); index < (ARRAY_SIZE * 2); ++index)
|
||||
{
|
||||
VTKM_TEST_ASSERT(array[index] == fillValue);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Reset with device data" << std::endl;
|
||||
std::vector<T> v(ARRAY_SIZE);
|
||||
void* devicePointer = v.data();
|
||||
|
Loading…
Reference in New Issue
Block a user