Update filters with secondary fields to use new policy method

Rather than do a CastAndCall on all possible field types when calling a
worklet with two fields (where they all typically get cast to the same
type as the primary field), use the new mechanism with
ArrayHandleMultiplexer to create one code path.

Also update the ApplyPolicy to accept the Field type, which is used to
determine any additional storage types to support.
This commit is contained in:
Kenneth Moreland 2019-09-08 00:09:14 -06:00
parent 3039a18baf
commit 07c59fcf72
13 changed files with 110 additions and 164 deletions

@ -21,7 +21,10 @@ type of the array as its first template argument, which must be specified.
This requires having a list of potential storage to try. It will use that
to construct an `ArrayHandleMultiplexer` containing all potential types.
This list of storages comes from the policy. A `StorageList` item was added
to the policy.
to the policy. It is also sometimes necessary for a filter to provide its
own special storage types. Thus, an `AdditionalFieldStorage` type was added
to `Filter` which is set to a `ListTag` of storage types that should be
added to those specified by the policy.
Types are automatically converted. So if you ask for a `vtkm::Float64` and
field contains a `vtkm::Float32`, it will the array wrapped in an
@ -33,12 +36,12 @@ result is just going to follow the type of the field.
``` cpp
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(
inline VTKM_CONT vtkm::cont::DataSet MyFilter::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
vtkm::cont::CoordinateSystem coords = inDataSet.GetCoordianteSystem();
auto coordsArray = vtkm::filter::ApplyPolicy<T>(coords, policy);
auto coordsArray = vtkm::filter::ApplyPolicy<T>(coords, policy, *this);
```

@ -17,31 +17,6 @@ namespace vtkm
namespace filter
{
namespace detail
{
struct CrossProductFunctor
{
vtkm::cont::Invoker& Invoke;
CrossProductFunctor(vtkm::cont::Invoker& invoke)
: Invoke(invoke)
{
}
template <typename SecondaryFieldType, typename StorageType, typename T>
void operator()(const SecondaryFieldType& secondaryField,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& primaryField,
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& output) const
{
this->Invoke(vtkm::worklet::CrossProduct{},
primaryField,
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<T, 3>>(secondaryField),
output);
}
};
} // namespace detail
//-----------------------------------------------------------------------------
inline VTKM_CONT CrossProduct::CrossProduct()
: vtkm::filter::FilterField<CrossProduct>()
@ -57,40 +32,23 @@ inline VTKM_CONT CrossProduct::CrossProduct()
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet CrossProduct::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& field,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& primary,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
detail::CrossProductFunctor functor(this->Invoke);
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> output;
try
{
vtkm::cont::Field secondaryField;
if (this->UseCoordinateSystemAsSecondaryField)
{
vtkm::cont::CastAndCall(
inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex()),
functor,
field,
output);
secondaryField = inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex());
}
else
{
using Traits = vtkm::filter::FilterTraits<CrossProduct>;
using TypeList = vtkm::ListTagBase<vtkm::Vec<T, 3>>;
vtkm::filter::ApplyPolicy(
inDataSet.GetField(this->SecondaryFieldName, this->SecondaryFieldAssociation),
policy,
Traits())
.ResetTypes(TypeList())
.CastAndCall(functor, field, output);
}
}
catch (const vtkm::cont::Error&)
{
throw vtkm::cont::ErrorExecution("failed to execute.");
secondaryField = inDataSet.GetField(this->SecondaryFieldName, this->SecondaryFieldAssociation);
}
auto secondary = vtkm::filter::ApplyPolicy<vtkm::Vec<T, 3>>(secondaryField, policy, *this);
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> output;
this->Invoke(vtkm::worklet::CrossProduct{}, primary, secondary, output);
return CreateResult(inDataSet, output, this->GetOutputFieldName(), fieldMetadata);
}

@ -15,31 +15,6 @@ namespace vtkm
namespace filter
{
namespace detail
{
struct DotProductFunctor
{
vtkm::cont::Invoker& Invoke;
DotProductFunctor(vtkm::cont::Invoker& invoke)
: Invoke(invoke)
{
}
template <typename SecondaryFieldType, typename StorageType, typename T>
void operator()(const SecondaryFieldType& secondaryField,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& primaryField,
vtkm::cont::ArrayHandle<T>& output) const
{
this->Invoke(vtkm::worklet::DotProduct{},
primaryField,
vtkm::cont::make_ArrayHandleCast<vtkm::Vec<T, 3>>(secondaryField),
output);
}
};
} // namespace detail
//-----------------------------------------------------------------------------
inline VTKM_CONT DotProduct::DotProduct()
: vtkm::filter::FilterField<DotProduct>()
@ -55,38 +30,23 @@ inline VTKM_CONT DotProduct::DotProduct()
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet DotProduct::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& field,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& primary,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
detail::DotProductFunctor functor(this->Invoke);
vtkm::cont::ArrayHandle<T> output;
try
{
vtkm::cont::Field secondaryField;
if (this->UseCoordinateSystemAsSecondaryField)
{
vtkm::cont::CastAndCall(
inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex()),
functor,
field,
output);
secondaryField = inDataSet.GetCoordinateSystem(this->GetSecondaryCoordinateSystemIndex());
}
else
{
using Traits = vtkm::filter::FilterTraits<DotProduct>;
using TypeList = vtkm::ListTagBase<vtkm::Vec<T, 3>>;
vtkm::filter::ApplyPolicy(
inDataSet.GetField(this->SecondaryFieldName, this->SecondaryFieldAssociation),
policy,
Traits())
.ResetTypes(TypeList())
.CastAndCall(functor, field, output);
}
}
catch (const vtkm::cont::Error&)
{
throw vtkm::cont::ErrorExecution("failed to execute.");
secondaryField = inDataSet.GetField(this->SecondaryFieldName, this->SecondaryFieldAssociation);
}
auto secondary = vtkm::filter::ApplyPolicy<vtkm::Vec<T, 3>>(secondaryField, policy, *this);
vtkm::cont::ArrayHandle<T> output;
this->Invoke(vtkm::worklet::DotProduct{}, primary, secondary, output);
return CreateResult(inDataSet, output, this->GetOutputFieldName(), fieldMetadata);
}

@ -179,7 +179,6 @@ public:
VTKM_CONT
~Filter();
//@{
/// \brief Specify which subset of types a filter supports.
///
/// A filter is able to state what subset of types it supports
@ -187,6 +186,16 @@ public:
/// filter accepts all types specified by the users provided policy
using SupportedTypes = vtkm::ListTagUniversal;
/// \brief Specify which additional field storage to support.
///
/// When a filter gets a field value from a DataSet, it has to determine what type
/// of storage the array has. Typically this is taken from the policy passed to
/// the filter's execute. In some cases it is useful to support additional types.
/// For example, the filter might make sense to support ArrayHandleIndex or
/// ArrayHandleConstant. If so, the storage of those additional types should be
/// listed here.
using AdditionalFieldStorage = vtkm::ListTagEmpty;
//@{
/// \brief Specify which fields get passed from input to output.
///

@ -35,6 +35,7 @@ struct FilterTraits
{
using InputFieldTypeList =
decltype(detail::as_list(std::declval<typename Filter::SupportedTypes>()));
using AdditionalFieldStorage = typename Filter::AdditionalFieldStorage;
};
template <typename DerivedPolicy, typename ListOfTypes>

@ -238,12 +238,19 @@ VTKM_CONT vtkm::cont::VariantArrayHandleBase<typename DerivedPolicy::FieldTypeLi
}
//-----------------------------------------------------------------------------
template <typename T, typename DerivedPolicy>
VTKM_CONT internal::ArrayHandleMultiplexerForStorageList<T, typename DerivedPolicy::StorageList>
ApplyPolicy(const vtkm::cont::Field& field, const vtkm::filter::PolicyBase<DerivedPolicy>&)
template <typename T, typename DerivedPolicy, typename FilterType>
VTKM_CONT internal::ArrayHandleMultiplexerForStorageList<
T,
vtkm::ListTagJoin<typename vtkm::filter::FilterTraits<FilterType>::AdditionalFieldStorage,
typename DerivedPolicy::StorageList>>
ApplyPolicy(const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>,
const FilterType&)
{
using ArrayHandleMultiplexerType =
internal::ArrayHandleMultiplexerForStorageList<T, typename DerivedPolicy::StorageList>;
using ArrayHandleMultiplexerType = internal::ArrayHandleMultiplexerForStorageList<
T,
vtkm::ListTagJoin<typename FilterType::AdditionalFieldStorage,
typename DerivedPolicy::StorageList>>;
return field.GetData().AsMultiplexer<ArrayHandleMultiplexerType>();
}
@ -253,8 +260,8 @@ VTKM_CONT vtkm::cont::VariantArrayHandleBase<typename vtkm::filter::DeduceFilter
DerivedPolicy,
typename vtkm::filter::FilterTraits<FilterType>::InputFieldTypeList>::TypeList>
ApplyPolicy(const vtkm::cont::Field& field,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
const vtkm::filter::FilterTraits<FilterType>&)
vtkm::filter::PolicyBase<DerivedPolicy>,
vtkm::filter::FilterTraits<FilterType>)
{
using FilterTypes = typename vtkm::filter::FilterTraits<FilterType>::InputFieldTypeList;
using TypeList =
@ -266,9 +273,7 @@ ApplyPolicy(const vtkm::cont::Field& field,
template <typename DerivedPolicy, typename ListOfTypes>
VTKM_CONT vtkm::cont::VariantArrayHandleBase<
typename vtkm::filter::DeduceFilterFieldTypes<DerivedPolicy, ListOfTypes>::TypeList>
ApplyPolicy(const vtkm::cont::Field& field,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
const ListOfTypes&)
ApplyPolicy(const vtkm::cont::Field& field, vtkm::filter::PolicyBase<DerivedPolicy>, ListOfTypes)
{
using TypeList =
typename vtkm::filter::DeduceFilterFieldTypes<DerivedPolicy, ListOfTypes>::TypeList;
@ -279,7 +284,7 @@ ApplyPolicy(const vtkm::cont::Field& field,
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DynamicCellSetBase<typename DerivedPolicy::AllCellSetList> ApplyPolicy(
const vtkm::cont::DynamicCellSet& cellset,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
vtkm::filter::PolicyBase<DerivedPolicy>)
{
using CellSetList = typename DerivedPolicy::AllCellSetList;
return cellset.ResetCellSetList(CellSetList());
@ -289,7 +294,7 @@ VTKM_CONT vtkm::cont::DynamicCellSetBase<typename DerivedPolicy::AllCellSetList>
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DynamicCellSetBase<typename DerivedPolicy::StructuredCellSetList>
ApplyPolicyStructured(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
vtkm::filter::PolicyBase<DerivedPolicy>)
{
using CellSetList = typename DerivedPolicy::StructuredCellSetList;
return cellset.ResetCellSetList(CellSetList());
@ -299,7 +304,7 @@ ApplyPolicyStructured(const vtkm::cont::DynamicCellSet& cellset,
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DynamicCellSetBase<typename DerivedPolicy::UnstructuredCellSetList>
ApplyPolicyUnstructured(const vtkm::cont::DynamicCellSet& cellset,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
vtkm::filter::PolicyBase<DerivedPolicy>)
{
using CellSetList = typename DerivedPolicy::UnstructuredCellSetList;
return cellset.ResetCellSetList(CellSetList());
@ -308,15 +313,14 @@ ApplyPolicyUnstructured(const vtkm::cont::DynamicCellSet& cellset,
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::SerializableField<typename DerivedPolicy::FieldTypeList>
MakeSerializableField(const vtkm::filter::PolicyBase<DerivedPolicy>&)
MakeSerializableField(vtkm::filter::PolicyBase<DerivedPolicy>)
{
return {};
}
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::SerializableField<typename DerivedPolicy::FieldTypeList>
MakeSerializableField(const vtkm::cont::Field& field,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
MakeSerializableField(const vtkm::cont::Field& field, vtkm::filter::PolicyBase<DerivedPolicy>)
{
return vtkm::cont::SerializableField<typename DerivedPolicy::FieldTypeList>{ field };
}
@ -324,7 +328,7 @@ MakeSerializableField(const vtkm::cont::Field& field,
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::SerializableDataSet<typename DerivedPolicy::FieldTypeList,
typename DerivedPolicy::AllCellSetList>
MakeSerializableDataSet(const vtkm::filter::PolicyBase<DerivedPolicy>&)
MakeSerializableDataSet(vtkm::filter::PolicyBase<DerivedPolicy>)
{
return {};
}
@ -332,8 +336,7 @@ MakeSerializableDataSet(const vtkm::filter::PolicyBase<DerivedPolicy>&)
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::SerializableDataSet<typename DerivedPolicy::FieldTypeList,
typename DerivedPolicy::AllCellSetList>
MakeSerializableDataSet(const vtkm::cont::DataSet& dataset,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
MakeSerializableDataSet(const vtkm::cont::DataSet& dataset, vtkm::filter::PolicyBase<DerivedPolicy>)
{
return vtkm::cont::SerializableDataSet<typename DerivedPolicy::FieldTypeList,
typename DerivedPolicy::AllCellSetList>{ dataset };

@ -12,6 +12,8 @@
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/filter/PolicyBase.h>
namespace vtkm
{
namespace filter
@ -27,18 +29,17 @@ inline VTKM_CONT Tube::Tube()
//-----------------------------------------------------------------------------
template <typename Policy>
inline VTKM_CONT vtkm::cont::DataSet Tube::DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<Policy>)
vtkm::filter::PolicyBase<Policy> policy)
{
this->Worklet.SetCapping(this->Capping);
this->Worklet.SetNumberOfSides(this->NumberOfSides);
this->Worklet.SetRadius(this->Radius);
auto originalPoints = vtkm::filter::ApplyPolicy<vtkm::Vec3f>(
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()), policy, *this);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
this->Worklet.Run(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()),
input.GetCellSet(),
newPoints,
newCells);
this->Worklet.Run(originalPoints, input.GetCellSet(), newPoints, newCells);
vtkm::cont::DataSet outData;
vtkm::cont::CoordinateSystem outCoords("coordinates", newPoints);

@ -32,6 +32,11 @@ public:
// WarpScalar can only applies to Float and Double Vec3 arrays
using SupportedTypes = vtkm::TypeListTagFieldVec3;
// WarpScalar often operates on a constant normal value
using AdditionalFieldStorage =
vtkm::ListTagBase<vtkm::cont::ArrayHandleConstant<vtkm::Vec3f_32>::StorageTag,
vtkm::cont::ArrayHandleConstant<vtkm::Vec3f_64>::StorageTag>;
VTKM_CONT
WarpScalar(vtkm::FloatDefault scaleAmount);

@ -35,13 +35,14 @@ inline VTKM_CONT vtkm::cont::DataSet WarpScalar::DoExecute(
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
using vecType = vtkm::Vec<T, 3>;
auto normalF = inDataSet.GetField(this->NormalFieldName, this->NormalFieldAssociation);
auto sfF = inDataSet.GetField(this->ScalarFactorFieldName, this->ScalarFactorFieldAssociation);
vtkm::cont::Field normalF =
inDataSet.GetField(this->NormalFieldName, this->NormalFieldAssociation);
vtkm::cont::Field sfF =
inDataSet.GetField(this->ScalarFactorFieldName, this->ScalarFactorFieldAssociation);
vtkm::cont::ArrayHandle<vecType> result;
this->Worklet.Run(
field,
vtkm::filter::ApplyPolicy(normalF, policy, vtkm::filter::FilterTraits<WarpScalar>()),
vtkm::filter::ApplyPolicy(sfF, policy, vtkm::TypeListTagFieldScalar{}),
this->Worklet.Run(field,
vtkm::filter::ApplyPolicy<vecType>(normalF, policy, *this),
vtkm::filter::ApplyPolicy<T>(sfF, policy, *this),
this->ScaleAmount,
result);

@ -30,6 +30,9 @@ class WarpVector : public vtkm::filter::FilterField<WarpVector>
{
public:
using SupportedTypes = vtkm::TypeListTagFieldVec3;
using AdditionalFieldStorage =
vtkm::ListTagBase<vtkm::cont::ArrayHandleConstant<vtkm::Vec3f_32>::StorageTag,
vtkm::cont::ArrayHandleConstant<vtkm::Vec3f_64>::StorageTag>;
VTKM_CONT
WarpVector(vtkm::FloatDefault scale);

@ -33,13 +33,11 @@ inline VTKM_CONT vtkm::cont::DataSet WarpVector::DoExecute(
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
using vecType = vtkm::Vec<T, 3>;
auto vectorF = inDataSet.GetField(this->VectorFieldName, this->VectorFieldAssociation);
vtkm::cont::Field vectorF =
inDataSet.GetField(this->VectorFieldName, this->VectorFieldAssociation);
vtkm::cont::ArrayHandle<vecType> result;
this->Worklet.Run(
field,
vtkm::filter::ApplyPolicy(vectorF, policy, vtkm::filter::FilterTraits<WarpVector>()),
this->Scale,
result);
field, vtkm::filter::ApplyPolicy<vecType>(vectorF, policy, *this), this->Scale, result);
return CreateResult(inDataSet, result, this->GetOutputFieldName(), fieldMetadata);
}

@ -536,18 +536,16 @@ public:
VTKM_CONT
void SetRadius(vtkm::FloatDefault r) { this->Radius = r; }
VTKM_CONT
void Run(const vtkm::cont::CoordinateSystem& coords,
template <typename Storage>
VTKM_CONT void Run(const vtkm::cont::ArrayHandle<vtkm::Vec3f, Storage>& coords,
const vtkm::cont::DynamicCellSet& cellset,
vtkm::cont::ArrayHandle<vtkm::Vec3f>& newPoints,
vtkm::cont::CellSetSingleType<>& newCells)
{
using ExplCoordsType = vtkm::cont::ArrayHandle<vtkm::Vec3f>;
using NormalsType = vtkm::cont::ArrayHandle<vtkm::Vec3f>;
if (!(coords.GetData().IsType<ExplCoordsType>() &&
(cellset.IsSameType(vtkm::cont::CellSetExplicit<>()) ||
cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))))
if (!cellset.IsSameType(vtkm::cont::CellSetExplicit<>()) &&
!cellset.IsSameType(vtkm::cont::CellSetSingleType<>()))
{
throw vtkm::cont::ErrorBadValue("Tube filter only supported for polyline data.");
}
@ -574,11 +572,10 @@ public:
vtkm::cont::Algorithm::ScanExclusive(segPerPolyline, segOffset);
//Generate normals at each point on all polylines
ExplCoordsType inCoords = coords.GetData().Cast<ExplCoordsType>();
NormalsType normals;
normals.Allocate(totalPolylinePts);
vtkm::worklet::DispatcherMapTopology<GenerateNormals> genNormalsDisp;
genNormalsDisp.Invoke(cellset, inCoords, polylinePtOffset, normals);
genNormalsDisp.Invoke(cellset, coords, polylinePtOffset, normals);
//Generate the tube points
newPoints.Allocate(totalTubePts);
@ -586,7 +583,7 @@ public:
GeneratePoints genPts(this->Capping, this->NumSides, this->Radius);
vtkm::worklet::DispatcherMapTopology<GeneratePoints> genPtsDisp(genPts);
genPtsDisp.Invoke(cellset,
inCoords,
coords,
normals,
tubePointOffsets,
polylinePtOffset,

@ -120,7 +120,10 @@ void TestTube(bool capEnds, vtkm::FloatDefault radius, vtkm::Id numSides, vtkm::
vtkm::worklet::Tube tubeWorklet(capEnds, numSides, radius);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
tubeWorklet.Run(ds.GetCoordinateSystem(0), ds.GetCellSet(), newPoints, newCells);
tubeWorklet.Run(ds.GetCoordinateSystem(0).GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
newPoints,
newCells);
VTKM_TEST_ASSERT(newPoints.GetNumberOfValues() == reqNumPts,
"Wrong number of points in Tube worklet");
@ -175,7 +178,11 @@ void TestLinearPolylines()
vtkm::worklet::Tube tubeWorklet(capEnds, numSides, radius);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
tubeWorklet.Run(ds.GetCoordinateSystem(0), ds.GetCellSet(), newPoints, newCells);
tubeWorklet.Run(
ds.GetCoordinateSystem(0).GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
newPoints,
newCells);
VTKM_TEST_ASSERT(newPoints.GetNumberOfValues() == reqNumPts,
"Wrong number of points in Tube worklet");