mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
5b34e6f70b
To avoid having to use a device compiler every time you wish to use `ArrayGetValue`, the actual implementation is compiled into the `vtkm_cont` library. To allow this to work for all the templated versions of `ArrayHandle`, the implementation uses the extract component features of `UnknownArrayHandle`. This works for most common arrays, but not all arrays. For arrays that cannot be directly represented by an `ArrayHandleStride`, the fallback is bad. The entire array has to be pulled to the host and then copied serially to a basic array. For `ArrayGetValue`, this is just silly. So, for arrays that cannot be simply represented by `ArrayHandleStride`, make a fallback that just uses `ReadPortal` to get the data. Often this is not the most efficient method, but it is better than the current alternative.
82 lines
3.1 KiB
C++
82 lines
3.1 KiB
C++
//============================================================================
|
|
// 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/ArrayGetValues.h>
|
|
|
|
#include <vtkm/cont/Algorithm.h>
|
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
|
#include <vtkm/cont/UnknownArrayHandle.h>
|
|
|
|
#include <vtkm/List.h>
|
|
#include <vtkm/TypeList.h>
|
|
|
|
void vtkm::cont::internal::ArrayGetValuesImpl(const vtkm::cont::UnknownArrayHandle& ids,
|
|
const vtkm::cont::UnknownArrayHandle& data,
|
|
const vtkm::cont::UnknownArrayHandle& output,
|
|
std::false_type)
|
|
{
|
|
auto idArray = ids.ExtractComponent<vtkm::Id>(0, vtkm::CopyFlag::On);
|
|
output.Allocate(ids.GetNumberOfValues());
|
|
|
|
bool copied = false;
|
|
vtkm::ListForEach(
|
|
[&](auto base) {
|
|
using T = decltype(base);
|
|
if (!copied && data.IsBaseComponentType<T>())
|
|
{
|
|
vtkm::IdComponent numComponents = data.GetNumberOfComponentsFlat();
|
|
VTKM_ASSERT(output.GetNumberOfComponentsFlat() == numComponents);
|
|
for (vtkm::IdComponent componentIdx = 0; componentIdx < numComponents; ++componentIdx)
|
|
{
|
|
auto dataArray = data.ExtractComponent<T>(componentIdx, vtkm::CopyFlag::On);
|
|
auto outputArray = output.ExtractComponent<T>(componentIdx, vtkm::CopyFlag::Off);
|
|
auto permutedArray = vtkm::cont::make_ArrayHandlePermutation(idArray, dataArray);
|
|
|
|
bool copiedComponent = false;
|
|
if (!dataArray.IsOnHost())
|
|
{
|
|
copiedComponent = vtkm::cont::TryExecute([&](auto device) {
|
|
if (dataArray.IsOnDevice(device))
|
|
{
|
|
vtkm::cont::DeviceAdapterAlgorithm<decltype(device)>::Copy(permutedArray,
|
|
outputArray);
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
|
|
if (!copiedComponent)
|
|
{ // Fallback to a control-side copy if the device copy fails or if the device
|
|
// is undefined or if the data were already on the host. In this case, the
|
|
// best we can do is grab the portals and copy one at a time on the host with
|
|
// a for loop.
|
|
const vtkm::Id numVals = ids.GetNumberOfValues();
|
|
auto inPortal = permutedArray.ReadPortal();
|
|
auto outPortal = outputArray.WritePortal();
|
|
for (vtkm::Id i = 0; i < numVals; ++i)
|
|
{
|
|
outPortal.Set(i, inPortal.Get(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
copied = true;
|
|
}
|
|
},
|
|
vtkm::TypeListBaseC{});
|
|
|
|
if (!copied)
|
|
{
|
|
throw vtkm::cont::ErrorBadType("Unable to get values from array of type " +
|
|
data.GetArrayTypeName());
|
|
}
|
|
}
|