vtk-m2/vtkm/filter/MapFieldPermutation.cxx
Kenneth Moreland 03c3f9e178 Update MapField helper functions to use extracted array components
Previously, the `MapFieldMergeAverage` and `MapFieldPermutation` helper
function had to iterate over every possible type and create a separate
code path. This change uses the new extract component functionality to
create separate code paths only for different component types. This both
requires less code (the common filter library dropped from 66MB to 42MB
on my Mac) and covers more cases (such as `Vec`s larger than 4
components).

To make the implementation easier, `UnknownArrayHandle` now can create a
new `UnknownArrayHandle` of the same `ValueType` but with the basic
storage (so you can work with read-only storage) and the ability to
allocate the unknown array.
2020-12-16 17:23:35 -07:00

134 lines
3.8 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/filter/MapFieldPermutation.h>
#include <vtkm/TypeList.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/internal/CastInvalidValue.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/filter/PolicyDefault.h>
namespace
{
template <typename T>
struct MapPermutationWorklet : vtkm::worklet::WorkletMapField
{
T InvalidValue;
explicit MapPermutationWorklet(T invalidValue)
: InvalidValue(invalidValue)
{
}
using ControlSignature = void(FieldIn permutationIndex, WholeArrayIn input, FieldOut output);
template <typename InputPortalType>
VTKM_EXEC void operator()(vtkm::Id permutationIndex, InputPortalType inputPortal, T& output) const
{
if ((permutationIndex >= 0) && (permutationIndex < inputPortal.GetNumberOfValues()))
{
output = inputPortal.Get(permutationIndex);
}
else
{
output = this->InvalidValue;
}
}
};
struct DoMapFieldPermutation
{
template <typename BaseComponentType>
void operator()(BaseComponentType,
const vtkm::cont::UnknownArrayHandle& input,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
vtkm::cont::UnknownArrayHandle& output,
vtkm::Float64 invalidValue,
bool& called) const
{
if (!input.IsBaseComponentType<BaseComponentType>())
{
return;
}
output = input.NewInstanceBasic();
output.Allocate(permutation.GetNumberOfValues());
vtkm::IdComponent numComponents = input.GetNumberOfComponentsFlat();
MapPermutationWorklet<BaseComponentType> worklet(
vtkm::cont::internal::CastInvalidValue<BaseComponentType>(invalidValue));
vtkm::cont::Invoker invoke;
for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex)
{
invoke(worklet,
permutation,
input.ExtractComponent<BaseComponentType>(cIndex, vtkm::CopyFlag::On),
output.ExtractComponent<BaseComponentType>(cIndex, vtkm::CopyFlag::Off));
}
called = true;
}
};
} // anonymous namespace
VTKM_FILTER_COMMON_EXPORT VTKM_CONT bool vtkm::filter::MapFieldPermutation(
const vtkm::cont::Field& inputField,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
vtkm::cont::Field& outputField,
vtkm::Float64 invalidValue)
{
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
vtkm::cont::VariantArrayHandle outputArray;
bool calledMap = false;
vtkm::ListForEach(DoMapFieldPermutation{},
vtkm::TypeListScalarAll{},
inputField.GetData(),
permutation,
outputArray,
invalidValue,
calledMap);
if (calledMap)
{
outputField = vtkm::cont::Field(inputField.GetName(), inputField.GetAssociation(), outputArray);
}
else
{
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Faild to map field " << inputField.GetName());
}
return calledMap;
}
VTKM_FILTER_COMMON_EXPORT VTKM_CONT bool vtkm::filter::MapFieldPermutation(
const vtkm::cont::Field& inputField,
const vtkm::cont::ArrayHandle<vtkm::Id>& permutation,
vtkm::cont::DataSet& outputData,
vtkm::Float64 invalidValue)
{
vtkm::cont::Field outputField;
bool success =
vtkm::filter::MapFieldPermutation(inputField, permutation, outputField, invalidValue);
if (success)
{
outputData.AddField(outputField);
}
return success;
}