mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Add Mask capabilities to worklets
Mask objects allow you to specify which output values should be generated when a worklet is run. That is, the Mask allows you to skip the invocation of a worklet for any number of outputs.
This commit is contained in:
parent
c27a33669b
commit
191d6e5580
104
docs/changelog/mask-worklets.md
Normal file
104
docs/changelog/mask-worklets.md
Normal file
@ -0,0 +1,104 @@
|
||||
# Allow masking of worklet invocations
|
||||
|
||||
There have recently been use cases where it would be helpful to mask out
|
||||
some of the invocations of a worklet. The idea is that when invoking a
|
||||
worklet with a mask array on the input domain, you might implement your
|
||||
worklet more-or-less like the following.
|
||||
|
||||
```cpp
|
||||
VTKM_EXEC void operator()(bool mask, /* other parameters */)
|
||||
{
|
||||
if (mask)
|
||||
{
|
||||
// Do interesting stuff
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This works, but what if your mask has mostly false values? In that case,
|
||||
you are spending tons of time loading data to and from memory where fields
|
||||
are stored for no reason.
|
||||
|
||||
You could potentially get around this problem by adding a scatter to the
|
||||
worklet. However, that will compress the output arrays to only values that
|
||||
are active in the mask. That is problematic if you want the masked output
|
||||
in the appropriate place in the original arrays. You will have to do some
|
||||
complex (and annoying and possibly expensive) permutations of the output
|
||||
arrays.
|
||||
|
||||
Thus, we would like a new feature similar to scatter that instead masks out
|
||||
invocations so that the worklet is simply not run on those outputs.
|
||||
|
||||
## New Interface
|
||||
|
||||
The new "Mask" feature that is similar (and orthogonal) to the existing
|
||||
"Scatter" feature. Worklet objects now define a `MaskType` that provides on
|
||||
object that manages the selections of which invocations are skipped. The
|
||||
following Mask objects are defined.
|
||||
|
||||
* `MaskNone` - This removes any mask of the output. All outputs are
|
||||
generated. This is the default if no `MaskType` is explicitly defined.
|
||||
* `MaskSelect` - The user to provides an array that specifies whether
|
||||
each output is created with a 1 to mean that the output should be
|
||||
created an 0 the mean that it should not.
|
||||
* `MaskIndices` - The user provides an array with a list of indices for
|
||||
all outputs that should be created.
|
||||
|
||||
It will be straightforward to implement other versions of masks. (For
|
||||
example, you could make a mask class that selectes every Nth entry.) Those
|
||||
could be made on an as-needed basis.
|
||||
|
||||
## Implementation
|
||||
|
||||
The implementation follows the same basic idea of how scatters are
|
||||
implemented.
|
||||
|
||||
### Mask Classes
|
||||
|
||||
The mask class is required to implement the following items.
|
||||
|
||||
* `ThreadToOutputType` - A type for an array that maps a thread index (an
|
||||
index in the array) to an output index. A reasonable type for this
|
||||
could be `vtkm::cont::ArrayHandle<vtkm::Id>`.
|
||||
* `GetThreadToOutputMap` - Given the range for the output (e.g. the
|
||||
number of items in the output domain), returns an array of type
|
||||
`ThreadToOutputType` that is the actual map.
|
||||
* `GetThreadRange` - Given a range for the output (e.g. the number of
|
||||
items in the output domain), returns the range for the threads (e.g.
|
||||
the number of times the worklet will be invoked).
|
||||
|
||||
### Dispatching
|
||||
|
||||
The `vtkm::worklet::internal::DispatcherBase` manages a mask class in
|
||||
the same way it manages the scatter class. It gets the `MaskType` from
|
||||
the worklet it is templated on. It requires a `MaskType` object during
|
||||
its construction.
|
||||
|
||||
Previously the dispatcher (and downstream) had to manage the range and
|
||||
indices of inputs and threads. They now have to also manage a separate
|
||||
output range/index as now all three may be different.
|
||||
|
||||
The `vtkm::Invocation` is changed to hold the ThreadToOutputMap array from
|
||||
the mask. It likewises has a templated `ChangeThreadToOutputMap` method
|
||||
added (similar to those already existing for the arrays from a scatter).
|
||||
This method is used in `DispatcherBase::InvokeTransportParameters` to add
|
||||
the mask's array to the invocation before calling `InvokeSchedule`.
|
||||
|
||||
### Thread Indices
|
||||
|
||||
With the addition of masks, the `ThreadIndices` classes are changed to
|
||||
manage the actual output index. Previously, the output index was always the
|
||||
same as the thread index. However, now these two can be different. The
|
||||
`GetThreadIndices` methods of the worklet base classes have an argument
|
||||
added that is the portal to the ThreadToOutputMap.
|
||||
|
||||
The worklet `GetThreadIndices` is called from the `Task` classes. These
|
||||
classes are changed to pass in this additional argument. Since the `Task`
|
||||
classes get an `Invocation` object from the dispatcher, which contains the
|
||||
`ThreadToOutputMap`, this change is trivial.
|
||||
|
||||
## Interaction Between Mask and Scatter
|
||||
|
||||
Although it seems weird, it should work fine to mix scatters and masks. The
|
||||
scatter will first be applied to the input to generate a (potential) list
|
||||
of output elements. The mask will then be applied to these output elements.
|
@ -49,14 +49,25 @@ public:
|
||||
ThreadIndicesBasic(vtkm::Id threadIndex,
|
||||
vtkm::Id inIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outIndex,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: InputIndex(inIndex)
|
||||
, OutputIndex(threadIndex)
|
||||
: ThreadIndex(threadIndex)
|
||||
, InputIndex(inIndex)
|
||||
, OutputIndex(outIndex)
|
||||
, VisitIndex(visitIndex)
|
||||
, GlobalThreadIndexOffset(globalThreadIndexOffset)
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief The index of the thread or work invocation.
|
||||
///
|
||||
/// This index refers to which instance of the worklet is being invoked. Every invocation of the
|
||||
/// worklet has a unique thread index. This is also called the work index depending on the
|
||||
/// context.
|
||||
///
|
||||
VTKM_EXEC
|
||||
vtkm::Id GetThreadIndex() const { return this->ThreadIndex; }
|
||||
|
||||
/// \brief The index into the input domain.
|
||||
///
|
||||
/// This index refers to the input element (array value, cell, etc.) that
|
||||
@ -98,9 +109,10 @@ public:
|
||||
///
|
||||
/// Global index (for streaming)
|
||||
VTKM_EXEC
|
||||
vtkm::Id GetGlobalIndex() const { return (this->GlobalThreadIndexOffset + this->OutputIndex); }
|
||||
vtkm::Id GetGlobalIndex() const { return (this->GlobalThreadIndexOffset + this->ThreadIndex); }
|
||||
|
||||
private:
|
||||
vtkm::Id ThreadIndex;
|
||||
vtkm::Id InputIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
vtkm::IdComponent VisitIndex;
|
||||
|
@ -65,19 +65,14 @@ class ThreadIndicesPointNeighborhood
|
||||
{
|
||||
|
||||
public:
|
||||
template <typename OutToInArrayType, typename VisitArrayType, vtkm::IdComponent Dimension>
|
||||
template <vtkm::IdComponent Dimension>
|
||||
VTKM_EXEC ThreadIndicesPointNeighborhood(
|
||||
const vtkm::Id3& outIndex,
|
||||
const OutToInArrayType&,
|
||||
const VisitArrayType&,
|
||||
const vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
|
||||
vtkm::TopologyElementTagPoint,
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(outIndex, detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(0)
|
||||
, OutputIndex(0)
|
||||
, VisitIndex(0)
|
||||
, GlobalThreadIndexOffset(globalThreadIndexOffset)
|
||||
{
|
||||
using ConnectivityType = vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
|
||||
@ -85,41 +80,27 @@ public:
|
||||
Dimension>;
|
||||
using ConnRangeType = typename ConnectivityType::SchedulingRangeType;
|
||||
const ConnRangeType index = detail::Deflate(outIndex, ConnRangeType());
|
||||
this->InputIndex = connectivity.LogicalToFlatToIndex(index);
|
||||
this->OutputIndex = this->InputIndex;
|
||||
}
|
||||
|
||||
template <typename OutToInArrayType, typename VisitArrayType, vtkm::IdComponent Dimension>
|
||||
VTKM_EXEC ThreadIndicesPointNeighborhood(
|
||||
const vtkm::Id& outIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
|
||||
vtkm::TopologyElementTagPoint,
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(detail::To3D(connectivity.FlatToLogicalToIndex(outToIn.Get(outIndex))),
|
||||
detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(outToIn.Get(outIndex))
|
||||
, OutputIndex(outIndex)
|
||||
, VisitIndex(static_cast<vtkm::IdComponent>(visit.Get(outIndex)))
|
||||
, GlobalThreadIndexOffset(globalThreadIndexOffset)
|
||||
{
|
||||
this->ThreadIndex = connectivity.LogicalToFlatToIndex(index);
|
||||
this->InputIndex = this->ThreadIndex;
|
||||
this->VisitIndex = 0;
|
||||
this->OutputIndex = this->ThreadIndex;
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent Dimension>
|
||||
VTKM_EXEC ThreadIndicesPointNeighborhood(
|
||||
const vtkm::Id& outIndex,
|
||||
const vtkm::Id& inIndex,
|
||||
const vtkm::IdComponent& visitIndex,
|
||||
vtkm::Id threadIndex,
|
||||
vtkm::Id inputIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outputIndex,
|
||||
const vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
|
||||
vtkm::TopologyElementTagPoint,
|
||||
Dimension>& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: State(detail::To3D(connectivity.FlatToLogicalToIndex(inIndex)),
|
||||
: State(detail::To3D(connectivity.FlatToLogicalToIndex(inputIndex)),
|
||||
detail::To3D(connectivity.GetPointDimensions()))
|
||||
, InputIndex(inIndex)
|
||||
, OutputIndex(outIndex)
|
||||
, ThreadIndex(threadIndex)
|
||||
, InputIndex(inputIndex)
|
||||
, OutputIndex(outputIndex)
|
||||
, VisitIndex(visitIndex)
|
||||
, GlobalThreadIndexOffset(globalThreadIndexOffset)
|
||||
{
|
||||
@ -128,6 +109,9 @@ public:
|
||||
VTKM_EXEC
|
||||
const vtkm::exec::BoundaryState& GetBoundaryState() const { return this->State; }
|
||||
|
||||
VTKM_EXEC
|
||||
vtkm::Id GetThreadIndex() const { return this->ThreadIndex; }
|
||||
|
||||
VTKM_EXEC
|
||||
vtkm::Id GetInputIndex() const { return this->InputIndex; }
|
||||
|
||||
@ -148,6 +132,7 @@ public:
|
||||
|
||||
private:
|
||||
vtkm::exec::BoundaryState State;
|
||||
vtkm::Id ThreadIndex;
|
||||
vtkm::Id InputIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
vtkm::IdComponent VisitIndex;
|
||||
|
@ -48,9 +48,10 @@ public:
|
||||
vtkm::Id threadIndex,
|
||||
vtkm::Id inIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outIndex,
|
||||
const vtkm::exec::internal::ReduceByKeyLookup<P1, P2, P3>& keyLookup,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: Superclass(threadIndex, inIndex, visitIndex, globalThreadIndexOffset)
|
||||
: Superclass(threadIndex, inIndex, visitIndex, outIndex, globalThreadIndexOffset)
|
||||
, ValueOffset(keyLookup.Offsets.Get(inIndex))
|
||||
, NumberOfValues(keyLookup.Counts.Get(inIndex))
|
||||
{
|
||||
|
@ -100,41 +100,20 @@ public:
|
||||
using CellShapeTag = typename ConnectivityType::CellShapeTag;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OutToInArrayType, typename VisitArrayType>
|
||||
VTKM_EXEC ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
vtkm::Id inputIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outputIndex,
|
||||
const ConnectivityType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: Superclass(threadIndex,
|
||||
outToIn.Get(threadIndex),
|
||||
visit.Get(threadIndex),
|
||||
globalThreadIndexOffset)
|
||||
: Superclass(threadIndex, inputIndex, visitIndex, outputIndex, globalThreadIndexOffset)
|
||||
// The connectivity is stored in the invocation parameter at the given
|
||||
// input domain index. If this class is being used correctly, the type
|
||||
// of the domain will match the connectivity type used here. If there is
|
||||
// a compile error here about a type mismatch, chances are a worklet has
|
||||
// set its input domain incorrectly.
|
||||
, IndicesFrom(connectivity.GetIndices(outToIn.Get(threadIndex)))
|
||||
, CellShape(connectivity.GetCellShape(outToIn.Get(threadIndex)))
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC
|
||||
ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
vtkm::Id inIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
const ConnectivityType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
: Superclass(threadIndex, inIndex, visitIndex, globalThreadIndexOffset)
|
||||
// The connectivity is stored in the invocation parameter at the given
|
||||
// input domain index. If this class is being used correctly, the type
|
||||
// of the domain will match the connectivity type used here. If there is
|
||||
// a compile error here about a type mismatch, chances are a worklet has
|
||||
// set its input domain incorrectly.
|
||||
, IndicesFrom(connectivity.GetIndices(inIndex))
|
||||
, CellShape(connectivity.GetCellShape(inIndex))
|
||||
, IndicesFrom(connectivity.GetIndices(inputIndex))
|
||||
, CellShape(connectivity.GetCellShape(inputIndex))
|
||||
{
|
||||
}
|
||||
|
||||
@ -187,61 +166,51 @@ public:
|
||||
using CellShapeTag = typename ConnectivityType::CellShapeTag;
|
||||
using LogicalIndexType = typename ConnectivityType::SchedulingRangeType;
|
||||
|
||||
template <typename OutToInArrayType, typename VisitArrayType>
|
||||
VTKM_EXEC ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
vtkm::Id inIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outIndex,
|
||||
const ConnectivityType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
{
|
||||
|
||||
this->InputIndex = outToIn.Get(threadIndex);
|
||||
this->OutputIndex = threadIndex;
|
||||
this->VisitIndex = visit.Get(threadIndex);
|
||||
this->ThreadIndex = threadIndex;
|
||||
this->InputIndex = inIndex;
|
||||
this->VisitIndex = visitIndex;
|
||||
this->OutputIndex = outIndex;
|
||||
this->LogicalIndex = connectivity.FlatToLogicalToIndex(this->InputIndex);
|
||||
this->IndicesFrom = connectivity.GetIndices(this->LogicalIndex);
|
||||
this->CellShape = connectivity.GetCellShape(this->InputIndex);
|
||||
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
|
||||
}
|
||||
|
||||
template <typename OutToInArrayType, typename VisitArrayType>
|
||||
VTKM_EXEC ThreadIndicesTopologyMap(const vtkm::Id3& threadIndex,
|
||||
const OutToInArrayType&,
|
||||
const VisitArrayType& visit,
|
||||
const ConnectivityType& connectivity,
|
||||
const vtkm::Id globalThreadIndexOffset = 0)
|
||||
{
|
||||
// We currently only support multidimensional indices on one-to-one input-
|
||||
// to-output mappings. (We don't have a use case otherwise.)
|
||||
// that is why the OutToInArrayType is ignored
|
||||
// That is why we treat teh threadIndex as also the inputIndex and outputIndex
|
||||
const LogicalIndexType logicalIndex = detail::Deflate(threadIndex, LogicalIndexType());
|
||||
const vtkm::Id index = connectivity.LogicalToFlatToIndex(logicalIndex);
|
||||
|
||||
this->ThreadIndex = index;
|
||||
this->InputIndex = index;
|
||||
this->OutputIndex = index;
|
||||
this->VisitIndex = visit.Get(index);
|
||||
this->VisitIndex = 0;
|
||||
this->LogicalIndex = logicalIndex;
|
||||
this->IndicesFrom = connectivity.GetIndices(logicalIndex);
|
||||
this->CellShape = connectivity.GetCellShape(index);
|
||||
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
/// \brief The index of the thread or work invocation.
|
||||
///
|
||||
/// This index refers to which instance of the worklet is being invoked. Every invocation of the
|
||||
/// worklet has a unique thread index. This is also called the work index depending on the
|
||||
/// context.
|
||||
///
|
||||
VTKM_EXEC
|
||||
ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
vtkm::Id vtkmNotUsed(inIndex),
|
||||
vtkm::IdComponent visitIndex,
|
||||
const ConnectivityType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
{
|
||||
this->InputIndex = threadIndex;
|
||||
this->OutputIndex = threadIndex;
|
||||
this->VisitIndex = visitIndex;
|
||||
this->LogicalIndex = connectivity.FlatToLogicalToIndex(this->InputIndex);
|
||||
this->IndicesFrom = connectivity.GetIndices(this->LogicalIndex);
|
||||
this->CellShape = connectivity.GetCellShape(this->InputIndex);
|
||||
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
|
||||
}
|
||||
vtkm::Id GetThreadIndex() const { return this->ThreadIndex; }
|
||||
|
||||
/// \brief The logical index into the input domain.
|
||||
///
|
||||
@ -321,9 +290,10 @@ public:
|
||||
CellShapeTag GetCellShape() const { return this->CellShape; }
|
||||
|
||||
private:
|
||||
vtkm::Id ThreadIndex;
|
||||
vtkm::Id InputIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
vtkm::IdComponent VisitIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
LogicalIndexType LogicalIndex;
|
||||
IndicesFromType IndicesFrom;
|
||||
CellShapeTag CellShape;
|
||||
@ -351,35 +321,17 @@ public:
|
||||
using CellShapeTag = typename ConnectivityType::CellShapeTag;
|
||||
using LogicalIndexType = typename ConnectivityType::SchedulingRangeType;
|
||||
|
||||
template <typename OutToInArrayType, typename VisitArrayType>
|
||||
VTKM_EXEC ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
vtkm::Id inputIndex,
|
||||
vtkm::IdComponent visitIndex,
|
||||
vtkm::Id outputIndex,
|
||||
const PermutedConnectivityType& permutation,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
{
|
||||
this->InputIndex = outToIn.Get(threadIndex);
|
||||
this->OutputIndex = threadIndex;
|
||||
this->VisitIndex = visit.Get(threadIndex);
|
||||
|
||||
const vtkm::Id permutedIndex = permutation.Portal.Get(this->InputIndex);
|
||||
this->LogicalIndex = permutation.Connectivity.FlatToLogicalToIndex(permutedIndex);
|
||||
this->IndicesFrom = permutation.Connectivity.GetIndices(this->LogicalIndex);
|
||||
this->CellShape = permutation.Connectivity.GetCellShape(permutedIndex);
|
||||
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC
|
||||
ThreadIndicesTopologyMap(vtkm::Id threadIndex,
|
||||
vtkm::Id vtkmNotUsed(inIndex),
|
||||
vtkm::IdComponent visitIndex,
|
||||
const PermutedConnectivityType& permutation,
|
||||
vtkm::Id globalThreadIndexOffset = 0)
|
||||
{
|
||||
this->InputIndex = threadIndex;
|
||||
this->OutputIndex = threadIndex;
|
||||
this->ThreadIndex = threadIndex;
|
||||
this->InputIndex = inputIndex;
|
||||
this->VisitIndex = visitIndex;
|
||||
this->OutputIndex = outputIndex;
|
||||
|
||||
const vtkm::Id permutedIndex = permutation.Portal.Get(this->InputIndex);
|
||||
this->LogicalIndex = permutation.Connectivity.FlatToLogicalToIndex(permutedIndex);
|
||||
@ -388,6 +340,15 @@ public:
|
||||
this->GlobalThreadIndexOffset = globalThreadIndexOffset;
|
||||
}
|
||||
|
||||
/// \brief The index of the thread or work invocation.
|
||||
///
|
||||
/// This index refers to which instance of the worklet is being invoked. Every invocation of the
|
||||
/// worklet has a unique thread index. This is also called the work index depending on the
|
||||
/// context.
|
||||
///
|
||||
VTKM_EXEC
|
||||
vtkm::Id GetThreadIndex() const { return this->ThreadIndex; }
|
||||
|
||||
/// \brief The logical index into the input domain.
|
||||
///
|
||||
/// This is similar to \c GetIndex3D except the Vec size matches the actual
|
||||
@ -466,9 +427,10 @@ public:
|
||||
CellShapeTag GetCellShape() const { return this->CellShape; }
|
||||
|
||||
private:
|
||||
vtkm::Id ThreadIndex;
|
||||
vtkm::Id InputIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
vtkm::IdComponent VisitIndex;
|
||||
vtkm::Id OutputIndex;
|
||||
LogicalIndexType LogicalIndex;
|
||||
IndicesFromType IndicesFrom;
|
||||
CellShapeTag CellShape;
|
||||
|
@ -45,14 +45,6 @@ struct TestPortal
|
||||
}
|
||||
};
|
||||
|
||||
struct TestIndexPortal
|
||||
{
|
||||
using ValueType = vtkm::Id;
|
||||
|
||||
VTKM_EXEC_CONT
|
||||
ValueType Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
template <typename NeighborhoodType, typename T>
|
||||
void verify_neighbors(NeighborhoodType neighbors, vtkm::Id index, vtkm::Id3 index3d, T)
|
||||
{
|
||||
@ -127,8 +119,7 @@ struct FetchArrayNeighborhoodInTests
|
||||
for (vtkm::Id i = 0; i < POINT_DIMS[0]; i++, index++)
|
||||
{
|
||||
index3d[0] = i;
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(
|
||||
index3d, vtkm::internal::NullType(), vtkm::internal::NullType(), connectivity);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(index3d, connectivity);
|
||||
|
||||
auto neighbors = fetch.Load(indices, execObject);
|
||||
|
||||
@ -149,8 +140,7 @@ struct FetchArrayNeighborhoodInTests
|
||||
//Verify that 1D scheduling works with neighborhoods
|
||||
for (vtkm::Id index = 0; index < (POINT_DIMS[0] * POINT_DIMS[1] * POINT_DIMS[2]); index++)
|
||||
{
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(
|
||||
index, TestIndexPortal(), TestIndexPortal(), connectivity);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood indices(index, index, 0, index, connectivity);
|
||||
|
||||
auto neighbors = fetch.Load(indices, execObject);
|
||||
|
||||
|
@ -82,8 +82,12 @@ struct FetchArrayTopologyMapInTests
|
||||
|
||||
FetchType fetch;
|
||||
|
||||
const vtkm::Id threadIndex = 0;
|
||||
const vtkm::Id outputIndex = invocation.ThreadToOutputMap.Get(threadIndex);
|
||||
const vtkm::Id inputIndex = invocation.OutputToInputMap.Get(outputIndex);
|
||||
const vtkm::IdComponent visitIndex = invocation.VisitArray.Get(outputIndex);
|
||||
ThreadIndicesType indices(
|
||||
0, invocation.OutputToInputMap, invocation.VisitArray, invocation.GetInputDomain());
|
||||
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain());
|
||||
|
||||
typename FetchType::ValueType value =
|
||||
fetch.Load(indices, invocation.Parameters.template GetParameter<ParamIndex>());
|
||||
@ -125,7 +129,8 @@ struct FetchArrayTopologyMapInTests
|
||||
BaseFunctionInterface(),
|
||||
BaseFunctionInterface(),
|
||||
TestIndexPortal(),
|
||||
TestZeroPortal()));
|
||||
TestZeroPortal(),
|
||||
TestIndexPortal()));
|
||||
}
|
||||
};
|
||||
|
||||
@ -157,20 +162,32 @@ void TryStructuredPointCoordinatesInvocation(const Invocation& invocation)
|
||||
vtkm::Vec<vtkm::FloatDefault, 3> origin = TestValue(0, vtkm::Vec<vtkm::FloatDefault, 3>());
|
||||
vtkm::Vec<vtkm::FloatDefault, 3> spacing = TestValue(1, vtkm::Vec<vtkm::FloatDefault, 3>());
|
||||
|
||||
vtkm::VecAxisAlignedPointCoordinates<NumDimensions> value = fetch.Load(
|
||||
ThreadIndicesType(
|
||||
0, invocation.OutputToInputMap, invocation.VisitArray, invocation.GetInputDomain()),
|
||||
invocation.Parameters.template GetParameter<ParamIndex>());
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
|
||||
{
|
||||
const vtkm::Id threadIndex = 0;
|
||||
const vtkm::Id outputIndex = invocation.ThreadToOutputMap.Get(threadIndex);
|
||||
const vtkm::Id inputIndex = invocation.OutputToInputMap.Get(outputIndex);
|
||||
const vtkm::IdComponent visitIndex = invocation.VisitArray.Get(outputIndex);
|
||||
vtkm::VecAxisAlignedPointCoordinates<NumDimensions> value =
|
||||
fetch.Load(ThreadIndicesType(
|
||||
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain()),
|
||||
invocation.Parameters.template GetParameter<ParamIndex>());
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
|
||||
}
|
||||
|
||||
origin[0] += spacing[0];
|
||||
value = fetch.Load(
|
||||
ThreadIndicesType(
|
||||
1, invocation.OutputToInputMap, invocation.VisitArray, invocation.GetInputDomain()),
|
||||
invocation.Parameters.template GetParameter<ParamIndex>());
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
|
||||
{
|
||||
const vtkm::Id threadIndex = 1;
|
||||
const vtkm::Id outputIndex = invocation.ThreadToOutputMap.Get(threadIndex);
|
||||
const vtkm::Id inputIndex = invocation.OutputToInputMap.Get(outputIndex);
|
||||
const vtkm::IdComponent visitIndex = invocation.VisitArray.Get(outputIndex);
|
||||
vtkm::VecAxisAlignedPointCoordinates<NumDimensions> value =
|
||||
fetch.Load(ThreadIndicesType(
|
||||
threadIndex, inputIndex, visitIndex, outputIndex, invocation.GetInputDomain()),
|
||||
invocation.Parameters.template GetParameter<ParamIndex>());
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetOrigin(), origin), "Bad origin.");
|
||||
VTKM_TEST_ASSERT(test_equal(value.GetSpacing(), spacing), "Bad spacing.");
|
||||
}
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent NumDimensions>
|
||||
@ -192,14 +209,16 @@ void TryStructuredPointCoordinates(
|
||||
BaseFunctionInterface(),
|
||||
BaseFunctionInterface(),
|
||||
TestIndexPortal(),
|
||||
TestZeroPortal()));
|
||||
TestZeroPortal(),
|
||||
TestIndexPortal()));
|
||||
// Try again with topology in argument 3 and point coordinates in argument 1
|
||||
TryStructuredPointCoordinatesInvocation<NumDimensions, 1>(vtkm::internal::make_Invocation<3>(
|
||||
BaseFunctionInterface().Replace<3>(connectivity).template Replace<1>(coordinates),
|
||||
BaseFunctionInterface(),
|
||||
BaseFunctionInterface(),
|
||||
TestIndexPortal(),
|
||||
TestZeroPortal()));
|
||||
TestZeroPortal(),
|
||||
TestIndexPortal()));
|
||||
}
|
||||
|
||||
void TryStructuredPointCoordinates()
|
||||
|
@ -87,6 +87,7 @@ public:
|
||||
this->Worklet.GetThreadIndices(index,
|
||||
this->Invocation.OutputToInputMap,
|
||||
this->Invocation.VisitArray,
|
||||
this->Invocation.ThreadToOutputMap,
|
||||
this->Invocation.GetInputDomain(),
|
||||
this->GlobalIndexOffset));
|
||||
}
|
||||
@ -157,6 +158,7 @@ public:
|
||||
this->Worklet.GetThreadIndices(index,
|
||||
this->Invocation.OutputToInputMap,
|
||||
this->Invocation.VisitArray,
|
||||
this->Invocation.ThreadToOutputMap,
|
||||
this->Invocation.GetInputDomain(),
|
||||
this->GlobalIndexOffset));
|
||||
}
|
||||
|
@ -74,6 +74,13 @@ struct MyVisitArrayPortal
|
||||
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
|
||||
};
|
||||
|
||||
struct MyThreadToOutputMapPortal
|
||||
{
|
||||
using ValueType = vtkm::Id;
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
struct TestFetchTagInput
|
||||
{
|
||||
};
|
||||
@ -169,14 +176,16 @@ using InvocationType1 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestExecutionInterface1,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
using InvocationType2 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
template <typename TaskType>
|
||||
static __global__ void ScheduleTaskStrided(TaskType task, vtkm::Id start, vtkm::Id end)
|
||||
@ -202,17 +211,20 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -227,17 +239,20 @@ struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -65,13 +65,15 @@ public:
|
||||
VTKM_EXEC void operator()(T index) const
|
||||
{
|
||||
//Todo: rename this function to DoTaskSingular
|
||||
detail::DoWorkletInvokeFunctor(this->Worklet,
|
||||
this->Invocation,
|
||||
this->Worklet.GetThreadIndices(index,
|
||||
this->Invocation.OutputToInputMap,
|
||||
this->Invocation.VisitArray,
|
||||
this->Invocation.GetInputDomain(),
|
||||
GlobalIndexOffset));
|
||||
detail::DoWorkletInvokeFunctor(
|
||||
this->Worklet,
|
||||
this->Invocation,
|
||||
this->Worklet.GetThreadIndices(index,
|
||||
this->Invocation.OutputToInputMap,
|
||||
this->Invocation.VisitArray,
|
||||
this->Invocation.ThreadToOutputMap,
|
||||
this->Invocation.GetInputDomain(),
|
||||
GlobalIndexOffset));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -91,6 +91,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1>
|
||||
@ -101,7 +102,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -147,7 +148,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1>
|
||||
VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
@ -157,7 +158,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -197,6 +198,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -208,7 +210,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -264,7 +266,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2>
|
||||
@ -275,7 +277,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -325,6 +327,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -337,7 +340,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -403,7 +406,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -415,7 +418,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -475,6 +478,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -488,7 +492,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -564,7 +568,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -577,7 +581,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -647,6 +651,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -661,7 +666,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -747,7 +752,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -761,7 +766,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -841,6 +846,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -856,7 +862,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -952,7 +958,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -967,7 +973,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -1057,6 +1063,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -1073,7 +1080,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -1179,7 +1186,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -1195,7 +1202,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -1295,6 +1302,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -1312,7 +1320,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -1428,7 +1436,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -1445,7 +1453,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -1555,6 +1563,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -1573,7 +1582,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -1699,7 +1708,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -1717,7 +1726,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -1837,6 +1846,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -1856,7 +1866,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -1992,7 +2002,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -2011,7 +2021,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -2141,6 +2151,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -2161,7 +2172,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -2307,7 +2318,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -2327,7 +2338,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -2467,6 +2478,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -2488,7 +2500,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -2644,7 +2656,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -2665,7 +2677,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -2815,6 +2827,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -2837,7 +2850,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -3003,7 +3016,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -3025,7 +3038,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -3185,6 +3198,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -3208,7 +3222,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -3384,7 +3398,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -3407,7 +3421,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -3577,6 +3591,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -3601,7 +3616,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -3787,7 +3802,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -3811,7 +3826,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -3991,6 +4006,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -4016,7 +4032,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -4212,7 +4228,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -4237,7 +4253,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -4427,6 +4443,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -4453,7 +4470,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -4659,7 +4676,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -4685,7 +4702,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -4885,6 +4902,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -4912,7 +4930,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -5128,7 +5146,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -5155,7 +5173,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -5365,6 +5383,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -5393,7 +5412,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -5619,7 +5638,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -5647,7 +5666,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
@ -5867,6 +5886,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename R,
|
||||
typename P1,
|
||||
@ -5896,7 +5916,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<R(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -6132,7 +6152,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
typename P1,
|
||||
typename P2,
|
||||
@ -6161,7 +6181,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<void(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
|
@ -153,6 +153,7 @@ template <typename WorkletType,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
$template_params(num_params)>
|
||||
VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
@ -162,7 +163,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<$signature(num_params)>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation = vtkm::internal::Invocation<ParameterInterface,
|
||||
@ -212,7 +213,7 @@ template <typename WorkletType,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType,
|
||||
typename VisitArrayType, typename ThreadToOutputMapType,
|
||||
typename ThreadIndicesType,
|
||||
$template_params(num_params, start=1)>
|
||||
VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
@ -222,7 +223,7 @@ VTKM_EXEC void DoWorkletInvokeFunctor(
|
||||
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>& invocation,
|
||||
VisitArrayType, ThreadToOutputMapType>& invocation,
|
||||
const ThreadIndicesType& threadIndices)
|
||||
{
|
||||
using Invocation =
|
||||
|
@ -76,6 +76,13 @@ struct MyVisitArrayPortal
|
||||
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
|
||||
};
|
||||
|
||||
struct MyThreadToOutputMapPortal
|
||||
{
|
||||
using ValueType = vtkm::Id;
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
struct TestFetchTagInput
|
||||
{
|
||||
};
|
||||
@ -181,14 +188,16 @@ using InvocationType1 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestExecutionInterface1,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
using InvocationType2 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
@ -201,33 +210,42 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const vtkm::Id& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutputArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const vtkm::Id3& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id index = vtkm::Dot(threadIndex, vtkm::Id3(1, 8, 64));
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
index, outToIn.Get(index), visit.Get(index), globalThreadIndexOffset);
|
||||
const vtkm::Id flatThreadIndex = vtkm::Dot(threadIndex, vtkm::Id3(1, 8, 64));
|
||||
const vtkm::Id outIndex = threadToOut.Get(flatThreadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(flatThreadIndex,
|
||||
outToIn.Get(outIndex),
|
||||
visit.Get(outIndex),
|
||||
outIndex,
|
||||
globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -241,33 +259,42 @@ struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
|
||||
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const vtkm::Id& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const vtkm::Id3& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutputArrayType& threadToOutput,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id index = vtkm::Dot(threadIndex, vtkm::Id3(1, 8, 64));
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
index, outToIn.Get(index), visit.Get(index), globalThreadIndexOffset);
|
||||
const vtkm::Id outputIndex = threadToOutput.Get(index);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(index,
|
||||
outToIn.Get(outputIndex),
|
||||
visit.Get(outputIndex),
|
||||
outputIndex,
|
||||
globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -64,6 +64,13 @@ struct MyVisitArrayPortal
|
||||
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
|
||||
};
|
||||
|
||||
struct MyThreadToOutputMapPortal
|
||||
{
|
||||
using ValueType = vtkm::Id;
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
struct TestFetchTagInput
|
||||
{
|
||||
};
|
||||
@ -159,14 +166,16 @@ using InvocationType1 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestExecutionInterface1,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
using InvocationType2 = vtkm::internal::Invocation<ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1,
|
||||
MyOutputToInputMapPortal,
|
||||
MyVisitArrayPortal>;
|
||||
MyVisitArrayPortal,
|
||||
MyThreadToOutputMapPortal>;
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
@ -180,17 +189,20 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
@ -205,17 +217,20 @@ struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -64,6 +64,13 @@ struct MyVisitArrayPortal
|
||||
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
|
||||
};
|
||||
|
||||
struct MyThreadToOutputMapPortal
|
||||
{
|
||||
using ValueType = vtkm::Id;
|
||||
VTKM_EXEC_CONT
|
||||
vtkm::Id Get(vtkm::Id index) const { return index; }
|
||||
};
|
||||
|
||||
struct TestFetchTagInput
|
||||
{
|
||||
};
|
||||
@ -163,28 +170,34 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const G& globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Invocation>
|
||||
void CallDoWorkletInvokeFunctor(const Invocation& invocation, vtkm::Id index)
|
||||
{
|
||||
const vtkm::Id outputIndex = invocation.ThreadToOutputMap.Get(index);
|
||||
vtkm::exec::internal::detail::DoWorkletInvokeFunctor(
|
||||
TestWorkletProxy(),
|
||||
invocation,
|
||||
vtkm::exec::arg::ThreadIndicesBasic(
|
||||
index, invocation.OutputToInputMap.Get(index), invocation.VisitArray.Get(index)));
|
||||
vtkm::exec::arg::ThreadIndicesBasic(index,
|
||||
invocation.OutputToInputMap.Get(outputIndex),
|
||||
invocation.VisitArray.Get(outputIndex),
|
||||
outputIndex));
|
||||
}
|
||||
|
||||
void TestDoWorkletInvoke()
|
||||
@ -204,7 +217,8 @@ void TestDoWorkletInvoke()
|
||||
TestControlInterface(),
|
||||
TestExecutionInterface1(),
|
||||
MyOutputToInputMapPortal(),
|
||||
MyVisitArrayPortal()),
|
||||
MyVisitArrayPortal(),
|
||||
MyThreadToOutputMapPortal()),
|
||||
1);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30, "Output value not set right.");
|
||||
@ -216,7 +230,8 @@ void TestDoWorkletInvoke()
|
||||
TestControlInterface(),
|
||||
TestExecutionInterface2(),
|
||||
MyOutputToInputMapPortal(),
|
||||
MyVisitArrayPortal()),
|
||||
MyVisitArrayPortal(),
|
||||
MyThreadToOutputMapPortal()),
|
||||
2);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30 * 2, "Output value not set right.");
|
||||
|
@ -66,6 +66,7 @@ void VTKM_NEVER_EXPORT TaskTiling1DExecute(void* w,
|
||||
worklet->GetThreadIndices(index,
|
||||
invocation->OutputToInputMap,
|
||||
invocation->VisitArray,
|
||||
invocation->ThreadToOutputMap,
|
||||
invocation->GetInputDomain(),
|
||||
globalIndexOffset));
|
||||
}
|
||||
@ -110,6 +111,7 @@ void VTKM_NEVER_EXPORT TaskTiling3DExecute(void* w,
|
||||
worklet->GetThreadIndices(index,
|
||||
invocation->OutputToInputMap,
|
||||
invocation->VisitArray,
|
||||
invocation->ThreadToOutputMap,
|
||||
invocation->GetInputDomain(),
|
||||
globalIndexOffset));
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ template <typename _ParameterInterface,
|
||||
typename _ExecutionInterface,
|
||||
vtkm::IdComponent _InputDomainIndex,
|
||||
typename _OutputToInputMapType = vtkm::internal::NullType,
|
||||
typename _VisitArrayType = vtkm::internal::NullType>
|
||||
typename _VisitArrayType = vtkm::internal::NullType,
|
||||
typename _ThreadToOutputMapType = vtkm::internal::NullType>
|
||||
struct Invocation
|
||||
{
|
||||
/// \brief The types of the parameters
|
||||
@ -90,15 +91,25 @@ struct Invocation
|
||||
///
|
||||
using VisitArrayType = _VisitArrayType;
|
||||
|
||||
/// \brief An array representing the thread to output map.
|
||||
///
|
||||
/// When a worklet is invoked, there is an optional mask operation that will
|
||||
/// prevent the worklet to be run on masked-out elements of the output. This
|
||||
/// is represented with a map where each thread points to an output it creates.
|
||||
///
|
||||
using ThreadToOutputMapType = _ThreadToOutputMapType;
|
||||
|
||||
/// \brief Default Invocation constructors that holds the given parameters
|
||||
/// by reference.
|
||||
VTKM_CONT
|
||||
Invocation(const ParameterInterface& parameters,
|
||||
OutputToInputMapType outputToInputMap = OutputToInputMapType(),
|
||||
VisitArrayType visitArray = VisitArrayType())
|
||||
VisitArrayType visitArray = VisitArrayType(),
|
||||
ThreadToOutputMapType threadToOutputMap = ThreadToOutputMapType())
|
||||
: Parameters(parameters)
|
||||
, OutputToInputMap(outputToInputMap)
|
||||
, VisitArray(visitArray)
|
||||
, ThreadToOutputMap(threadToOutputMap)
|
||||
{
|
||||
}
|
||||
|
||||
@ -113,7 +124,8 @@ struct Invocation
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>;
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -124,7 +136,7 @@ struct Invocation
|
||||
const NewParameterInterface& newParameters) const
|
||||
{
|
||||
return typename ChangeParametersType<NewParameterInterface>::type(
|
||||
newParameters, this->OutputToInputMap, this->VisitArray);
|
||||
newParameters, this->OutputToInputMap, this->VisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
@ -133,8 +145,13 @@ struct Invocation
|
||||
template <typename NewControlInterface>
|
||||
struct ChangeControlInterfaceType
|
||||
{
|
||||
using type =
|
||||
Invocation<ParameterInterface, NewControlInterface, ExecutionInterface, InputDomainIndex>;
|
||||
using type = Invocation<ParameterInterface,
|
||||
NewControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -145,7 +162,7 @@ struct Invocation
|
||||
NewControlInterface) const
|
||||
{
|
||||
return typename ChangeControlInterfaceType<NewControlInterface>::type(
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray);
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
@ -154,8 +171,13 @@ struct Invocation
|
||||
template <typename NewExecutionInterface>
|
||||
struct ChangeExecutionInterfaceType
|
||||
{
|
||||
using type =
|
||||
Invocation<ParameterInterface, NewExecutionInterface, ExecutionInterface, InputDomainIndex>;
|
||||
using type = Invocation<ParameterInterface,
|
||||
NewExecutionInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -166,7 +188,7 @@ struct Invocation
|
||||
NewExecutionInterface) const
|
||||
{
|
||||
return typename ChangeExecutionInterfaceType<NewExecutionInterface>::type(
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray);
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
@ -175,8 +197,13 @@ struct Invocation
|
||||
template <vtkm::IdComponent NewInputDomainIndex>
|
||||
struct ChangeInputDomainIndexType
|
||||
{
|
||||
using type =
|
||||
Invocation<ParameterInterface, ControlInterface, ExecutionInterface, NewInputDomainIndex>;
|
||||
using type = Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
NewInputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -187,7 +214,7 @@ struct Invocation
|
||||
ChangeInputDomainIndex() const
|
||||
{
|
||||
return typename ChangeInputDomainIndexType<NewInputDomainIndex>::type(
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray);
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
@ -201,7 +228,8 @@ struct Invocation
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
NewOutputToInputMapType,
|
||||
VisitArrayType>;
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -212,7 +240,7 @@ struct Invocation
|
||||
ChangeOutputToInputMap(NewOutputToInputMapType newOutputToInputMap) const
|
||||
{
|
||||
return typename ChangeOutputToInputMapType<NewOutputToInputMapType>::type(
|
||||
this->Parameters, newOutputToInputMap, this->VisitArray);
|
||||
this->Parameters, newOutputToInputMap, this->VisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
@ -226,7 +254,8 @@ struct Invocation
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
NewVisitArrayType>;
|
||||
NewVisitArrayType,
|
||||
ThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -237,7 +266,33 @@ struct Invocation
|
||||
NewVisitArrayType newVisitArray) const
|
||||
{
|
||||
return typename ChangeVisitArrayType<NewVisitArrayType>::type(
|
||||
this->Parameters, this->OutputToInputMap, newVisitArray);
|
||||
this->Parameters, this->OutputToInputMap, newVisitArray, this->ThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
/// with the \c ThreadToOutputMapType replaced.
|
||||
///
|
||||
template <typename NewThreadToOutputMapType>
|
||||
struct ChangeThreadToOutputMapType
|
||||
{
|
||||
using type = Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType,
|
||||
NewThreadToOutputMapType>;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
/// \c OutputToInputMap is replaced with that provided.
|
||||
///
|
||||
template <typename NewThreadToOutputMapType>
|
||||
VTKM_CONT typename ChangeThreadToOutputMapType<NewThreadToOutputMapType>::type
|
||||
ChangeThreadToOutputMap(NewThreadToOutputMapType newThreadToOutputMap) const
|
||||
{
|
||||
return typename ChangeThreadToOutputMapType<NewThreadToOutputMapType>::type(
|
||||
this->Parameters, this->OutputToInputMap, this->VisitArray, newThreadToOutputMap);
|
||||
}
|
||||
|
||||
/// A convenience alias for the input domain type.
|
||||
@ -268,6 +323,7 @@ struct Invocation
|
||||
ParameterInterface Parameters;
|
||||
OutputToInputMapType OutputToInputMap;
|
||||
VisitArrayType VisitArray;
|
||||
ThreadToOutputMapType ThreadToOutputMap;
|
||||
|
||||
private:
|
||||
// Do not allow assignment of one Invocation to another. It is too expensive.
|
||||
@ -276,7 +332,8 @@ private:
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>&) = delete;
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>&) = delete;
|
||||
};
|
||||
|
||||
/// Convenience function for creating an Invocation object.
|
||||
@ -286,25 +343,30 @@ template <vtkm::IdComponent InputDomainIndex,
|
||||
typename ExecutionInterface,
|
||||
typename ParameterInterface,
|
||||
typename OutputToInputMapType,
|
||||
typename VisitArrayType>
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutputMapType>
|
||||
VTKM_CONT vtkm::internal::Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>
|
||||
make_Invocation(const ParameterInterface& params,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
OutputToInputMapType outputToInputMap,
|
||||
VisitArrayType visitArray)
|
||||
VisitArrayType visitArray,
|
||||
ThreadToOutputMapType threadToOutputMap)
|
||||
{
|
||||
return vtkm::internal::Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex,
|
||||
OutputToInputMapType,
|
||||
VisitArrayType>(params, outputToInputMap, visitArray);
|
||||
VisitArrayType,
|
||||
ThreadToOutputMapType>(
|
||||
params, outputToInputMap, visitArray, threadToOutputMap);
|
||||
}
|
||||
template <vtkm::IdComponent InputDomainIndex,
|
||||
typename ControlInterface,
|
||||
@ -320,6 +382,7 @@ VTKM_CONT vtkm::internal::
|
||||
ControlInterface(),
|
||||
ExecutionInterface(),
|
||||
vtkm::internal::NullType(),
|
||||
vtkm::internal::NullType(),
|
||||
vtkm::internal::NullType());
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,10 @@ set(headers
|
||||
Magnitude.h
|
||||
MarchingCubes.h
|
||||
Mask.h
|
||||
MaskIndices.h
|
||||
MaskNone.h
|
||||
MaskPoints.h
|
||||
MaskSelect.h
|
||||
NDimsEntropy.h
|
||||
NDimsHistMarginalization.h
|
||||
NDimsHistogram.h
|
||||
@ -107,6 +110,7 @@ set(sources_no_device
|
||||
# be compiled with a device-specific compiler (like CUDA).
|
||||
set(sources_device
|
||||
Keys.cxx
|
||||
MaskSelect.cxx
|
||||
ScatterCounting.cxx
|
||||
)
|
||||
|
||||
|
@ -42,21 +42,9 @@ class DispatcherMapField
|
||||
using ScatterType = typename Superclass::ScatterType;
|
||||
|
||||
public:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct
|
||||
// the scatter). By convention, worklets that define a custom scatter type usually provide a
|
||||
// static method named MakeScatter that constructs a scatter object.
|
||||
VTKM_CONT
|
||||
DispatcherMapField(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Superclass(worklet, scatter)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
DispatcherMapField(const ScatterType& scatter)
|
||||
: Superclass(WorkletType(), scatter)
|
||||
template <typename... T>
|
||||
VTKM_CONT DispatcherMapField(T&&... args)
|
||||
: Superclass(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,21 +45,9 @@ class DispatcherMapTopology
|
||||
using ScatterType = typename Superclass::ScatterType;
|
||||
|
||||
public:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct
|
||||
// the scatter). By convention, worklets that define a custom scatter type usually provide a
|
||||
// static method named MakeScatter that constructs a scatter object.
|
||||
VTKM_CONT
|
||||
DispatcherMapTopology(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Superclass(worklet, scatter)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
DispatcherMapTopology(const ScatterType& scatter)
|
||||
: Superclass(WorkletType(), scatter)
|
||||
template <typename... T>
|
||||
VTKM_CONT DispatcherMapTopology(T&&... args)
|
||||
: Superclass(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -46,21 +46,9 @@ class DispatcherPointNeighborhood
|
||||
using ScatterType = typename Superclass::ScatterType;
|
||||
|
||||
public:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct
|
||||
// the scatter). By convention, worklets that define a custom scatter type usually provide a
|
||||
// static method named MakeScatter that constructs a scatter object.
|
||||
VTKM_CONT
|
||||
DispatcherPointNeighborhood(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Superclass(worklet, scatter)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
DispatcherPointNeighborhood(const ScatterType& scatter)
|
||||
: Superclass(WorkletType(), scatter)
|
||||
template <typename... T>
|
||||
VTKM_CONT DispatcherPointNeighborhood(T&&... args)
|
||||
: Superclass(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -45,21 +45,9 @@ class DispatcherReduceByKey
|
||||
using ScatterType = typename Superclass::ScatterType;
|
||||
|
||||
public:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct
|
||||
// the scatter). By convention, worklets that define a custom scatter type usually provide a
|
||||
// static method named MakeScatter that constructs a scatter object.
|
||||
VTKM_CONT
|
||||
DispatcherReduceByKey(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Superclass(worklet, scatter)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
DispatcherReduceByKey(const ScatterType& scatter)
|
||||
: Superclass(WorkletType(), scatter)
|
||||
template <typename... T>
|
||||
VTKM_CONT DispatcherReduceByKey(T&&... args)
|
||||
: Superclass(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -189,24 +189,12 @@ class DispatcherStreamingMapField
|
||||
WorkletType,
|
||||
vtkm::worklet::WorkletMapField>;
|
||||
using ScatterType = typename Superclass::ScatterType;
|
||||
using MaskType = typename WorkletType::MaskType;
|
||||
|
||||
public:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct
|
||||
// the scatter). By convention, worklets that define a custom scatter type usually provide a
|
||||
// static method named MakeScatter that constructs a scatter object.
|
||||
VTKM_CONT
|
||||
DispatcherStreamingMapField(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Superclass(worklet, scatter)
|
||||
, NumberOfBlocks(1)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
DispatcherStreamingMapField(const ScatterType& scatter)
|
||||
: Superclass(WorkletType(), scatter)
|
||||
template <typename... T>
|
||||
VTKM_CONT DispatcherStreamingMapField(T&&... args)
|
||||
: Superclass(std::forward<T>(args)...)
|
||||
, NumberOfBlocks(1)
|
||||
{
|
||||
}
|
||||
@ -312,11 +300,16 @@ private:
|
||||
this->Scatter.GetOutputToInputMap(inputRange);
|
||||
typename ScatterType::VisitArrayType visitArray = this->Scatter.GetVisitArray(inputRange);
|
||||
|
||||
// Get the arrays used for masking output elements.
|
||||
typename MaskType::ThreadToOutputMapType threadToOutputMap =
|
||||
this->Mask.GetThreadToOutputMap(inputRange);
|
||||
|
||||
// Replace the parameters in the invocation with the execution object and
|
||||
// pass to next step of Invoke. Also add the scatter information.
|
||||
this->InvokeSchedule(invocation.ChangeParameters(execObjectParameters)
|
||||
.ChangeOutputToInputMap(outputToInputMap.PrepareForInput(device))
|
||||
.ChangeVisitArray(visitArray.PrepareForInput(device)),
|
||||
.ChangeVisitArray(visitArray.PrepareForInput(device))
|
||||
.ChangeThreadToOutputMap(threadToOutputMap.PrepareForInput(device)),
|
||||
outputRange,
|
||||
globalIndexOffset,
|
||||
device);
|
||||
|
@ -597,7 +597,7 @@ public:
|
||||
//Optimization for structured cellsets so we can call StructuredPointGradient
|
||||
//and have way faster gradients
|
||||
vtkm::exec::ConnectivityStructured<Cell, Point, 3> pointGeom(geometry);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointId, pointGeom, 0);
|
||||
|
||||
const auto& boundary = tpn.GetBoundaryState();
|
||||
auto pointPortal = pointCoordinates.GetPortal();
|
||||
@ -681,7 +681,7 @@ public:
|
||||
//Optimization for structured cellsets so we can call StructuredPointGradient
|
||||
//and have way faster gradients
|
||||
vtkm::exec::ConnectivityStructured<Cell, Point, 3> pointGeom(geometry);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointGeom, 0);
|
||||
vtkm::exec::arg::ThreadIndicesPointNeighborhood tpn(pointId, pointId, 0, pointId, pointGeom, 0);
|
||||
|
||||
const auto& boundary = tpn.GetBoundaryState();
|
||||
auto pointPortal = pointCoordinates.GetPortal();
|
||||
|
93
vtkm/worklet/MaskIndices.h
Normal file
93
vtkm/worklet/MaskIndices.h
Normal file
@ -0,0 +1,93 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef vtk_m_worklet_MaskIndices_h
|
||||
#define vtk_m_worklet_MaskIndices_h
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
|
||||
/// \brief Mask using a given array of indices to include in the output.
|
||||
///
|
||||
/// \c MaskIndices is a worklet mask object that is used to select elements in the output of a
|
||||
/// worklet to include in the output. This is done by providing a mask array. This array contains
|
||||
/// an entry for every output to create. Any output index not included is not generated.
|
||||
///
|
||||
/// It is OK to give indices that are out of order, but any index must be provided at most one
|
||||
/// time. It is an error to have the same index listed twice.
|
||||
///
|
||||
class MaskIndices
|
||||
{
|
||||
public:
|
||||
using ThreadToOutputMapType = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
|
||||
//@{
|
||||
/// \brief Construct using an index array.
|
||||
///
|
||||
/// When you construct a \c MaskSelect with the \c IndexArray tag, you provide an array
|
||||
/// containing an index for each output to produce. It is OK to give indices that are out of
|
||||
/// order, but any index must be provided at most one time. It is an error to have the same index
|
||||
/// listed twice.
|
||||
///
|
||||
/// Note that depending on the type of the array passed in, the index may be shallow copied
|
||||
/// or deep copied into the state of this mask object. Thus, it is a bad idea to alter the
|
||||
/// array once given to this object.
|
||||
///
|
||||
explicit MaskIndices(
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& indexArray,
|
||||
vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
this->ThreadToOutputMap = indexArray;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
explicit MaskIndices(const vtkm::cont::ArrayHandle<T, S>& indexArray,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
vtkm::cont::Algorithm::Copy(device, indexArray, this->ThreadToOutputMap);
|
||||
}
|
||||
//@}
|
||||
|
||||
// TODO? Create a version that accepts a VariantArrayHandle. Is this needed?
|
||||
|
||||
template <typename RangeType>
|
||||
vtkm::Id GetThreadRange(RangeType vtkmNotUsed(outputRange)) const
|
||||
{
|
||||
return this->ThreadToOutputMap.GetNumberOfValues();
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
ThreadToOutputMapType GetThreadToOutputMap(RangeType vtkmNotUsed(outputRange)) const
|
||||
{
|
||||
return this->ThreadToOutputMap;
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadToOutputMapType ThreadToOutputMap;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::worklet
|
||||
|
||||
#endif //vtk_m_worklet_MaskIndices_h
|
61
vtkm/worklet/MaskNone.h
Normal file
61
vtkm/worklet/MaskNone.h
Normal file
@ -0,0 +1,61 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef vtk_m_worklet_MaskNone_h
|
||||
#define vtk_m_worklet_MaskNone_h
|
||||
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
|
||||
/// \brief Default mask object that does not suppress anything.
|
||||
///
|
||||
/// \c MaskNone is a worklet mask object that does not suppress any items in the output
|
||||
/// domain. This is the default mask object so that the worklet is run for every possible
|
||||
/// output element.
|
||||
///
|
||||
struct MaskNone
|
||||
{
|
||||
template <typename RangeType>
|
||||
VTKM_CONT RangeType GetThreadRange(RangeType outputRange) const
|
||||
{
|
||||
return outputRange;
|
||||
}
|
||||
|
||||
using ThreadToOutputMapType = vtkm::cont::ArrayHandleIndex;
|
||||
|
||||
VTKM_CONT ThreadToOutputMapType GetThreadToOutputMap(vtkm::Id outputRange) const
|
||||
{
|
||||
return vtkm::cont::ArrayHandleIndex(outputRange);
|
||||
}
|
||||
|
||||
VTKM_CONT ThreadToOutputMapType GetThreadToOutputMap(const vtkm::Id3& outputRange) const
|
||||
{
|
||||
return this->GetThreadToOutputMap(outputRange[0] * outputRange[1] * outputRange[2]);
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::worklet
|
||||
|
||||
#endif //vtk_m_worklet_MaskNone_h
|
133
vtkm/worklet/MaskSelect.cxx
Normal file
133
vtkm/worklet/MaskSelect.cxx
Normal file
@ -0,0 +1,133 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <vtkm/worklet/MaskSelect.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayHandleCast.h>
|
||||
#include <vtkm/cont/ArrayHandleView.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ReverseOutputToThreadMap : vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn outputToThreadMap,
|
||||
FieldIn maskArray,
|
||||
WholeArrayOut threadToOutputMap);
|
||||
using ExecutionSignature = void(_1, InputIndex, _2, _3);
|
||||
|
||||
template <typename MaskType, typename ThreadToOutputPortal>
|
||||
VTKM_EXEC void operator()(vtkm::Id threadIndex,
|
||||
vtkm::Id outputIndex,
|
||||
MaskType mask,
|
||||
ThreadToOutputPortal threadToOutput) const
|
||||
{
|
||||
if (mask)
|
||||
{
|
||||
threadToOutput.Set(threadIndex, outputIndex);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT static vtkm::worklet::MaskSelect::ThreadToOutputMapType BuildThreadToOutputMapWithFind(
|
||||
vtkm::Id numThreads,
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> outputToThreadMap,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
vtkm::worklet::MaskSelect::ThreadToOutputMapType threadToOutputMap;
|
||||
|
||||
vtkm::Id outputSize = outputToThreadMap.GetNumberOfValues();
|
||||
|
||||
vtkm::cont::ArrayHandleIndex threadIndices(numThreads);
|
||||
vtkm::cont::Algorithm::UpperBounds(
|
||||
device,
|
||||
vtkm::cont::make_ArrayHandleView(outputToThreadMap, 1, outputSize - 1),
|
||||
threadIndices,
|
||||
threadToOutputMap);
|
||||
|
||||
return threadToOutputMap;
|
||||
}
|
||||
|
||||
template <typename MaskArrayType>
|
||||
VTKM_CONT static vtkm::worklet::MaskSelect::ThreadToOutputMapType BuildThreadToOutputMapWithCopy(
|
||||
vtkm::Id numThreads,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id>& outputToThreadMap,
|
||||
const MaskArrayType& maskArray,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
vtkm::worklet::MaskSelect::ThreadToOutputMapType threadToOutputMap;
|
||||
threadToOutputMap.Allocate(numThreads);
|
||||
|
||||
vtkm::worklet::DispatcherMapField<ReverseOutputToThreadMap> dispatcher;
|
||||
dispatcher.SetDevice(device);
|
||||
dispatcher.Invoke(outputToThreadMap, maskArray, threadToOutputMap);
|
||||
|
||||
return threadToOutputMap;
|
||||
}
|
||||
|
||||
struct MaskBuilder
|
||||
{
|
||||
template <typename ArrayHandleType>
|
||||
void operator()(const ArrayHandleType& maskArray,
|
||||
vtkm::worklet::MaskSelect::ThreadToOutputMapType& threadToOutputMap,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> outputToThreadMap;
|
||||
vtkm::Id numThreads = vtkm::cont::Algorithm::ScanExclusive(
|
||||
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(maskArray), outputToThreadMap);
|
||||
VTKM_ASSERT(numThreads < maskArray.GetNumberOfValues());
|
||||
|
||||
// We have implemented two different ways to compute the thread to output map. The first way is
|
||||
// to use a binary search on each thread index into the output map. The second way is to
|
||||
// schedule on each output and copy the the index to the thread map. The first way is faster
|
||||
// for output sizes that are small relative to the input and also tends to be well load
|
||||
// balanced. The second way is faster for larger outputs.
|
||||
//
|
||||
// The former is obviously faster for one thread and the latter is obviously faster when all
|
||||
// outputs have a thread. We have to guess for values in the middle. I'm using if the square of
|
||||
// the number of threads is less than the number of outputs because it is easy to compute.
|
||||
if ((numThreads * numThreads) < maskArray.GetNumberOfValues())
|
||||
{
|
||||
threadToOutputMap = BuildThreadToOutputMapWithFind(numThreads, outputToThreadMap, device);
|
||||
}
|
||||
else
|
||||
{
|
||||
threadToOutputMap =
|
||||
BuildThreadToOutputMapWithCopy(numThreads, outputToThreadMap, maskArray, device);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
vtkm::worklet::MaskSelect::ThreadToOutputMapType vtkm::worklet::MaskSelect::Build(
|
||||
const VariantArrayHandleMask& maskArray,
|
||||
vtkm::cont::DeviceAdapterId device)
|
||||
{
|
||||
vtkm::worklet::MaskSelect::ThreadToOutputMapType threadToOutputMap;
|
||||
maskArray.CastAndCall(MaskBuilder(), threadToOutputMap, device);
|
||||
return threadToOutputMap;
|
||||
}
|
94
vtkm/worklet/MaskSelect.h
Normal file
94
vtkm/worklet/MaskSelect.h
Normal file
@ -0,0 +1,94 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#ifndef vtk_m_worklet_MaskSelect_h
|
||||
#define vtk_m_worklet_MaskSelect_h
|
||||
|
||||
#include <vtkm/worklet/vtkm_worklet_export.h>
|
||||
|
||||
#include <vtkm/cont/VariantArrayHandle.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
|
||||
/// \brief Mask using arrays to select specific elements to suppress.
|
||||
///
|
||||
/// \c MaskSelect is a worklet mask object that is used to select elementsin the output of a
|
||||
/// worklet to suppress the invocation. That is, the worklet will only be invoked for elements in
|
||||
/// the output that are not masked out by the given array.
|
||||
///
|
||||
/// \c MaskSelect is initialized with a mask array. This array should contain a 0 for any entry
|
||||
/// that should be masked and a 1 for any output that should be generated. It is an error to have
|
||||
/// any value that is not a 0 or 1. This method is slower than specifying an index array.
|
||||
///
|
||||
class VTKM_WORKLET_EXPORT MaskSelect
|
||||
{
|
||||
struct MaskTypes : vtkm::ListTagBase<vtkm::Int32,
|
||||
vtkm::Int64,
|
||||
vtkm::UInt32,
|
||||
vtkm::UInt64,
|
||||
vtkm::Int8,
|
||||
vtkm::UInt8,
|
||||
char>
|
||||
{
|
||||
};
|
||||
using VariantArrayHandleMask = vtkm::cont::VariantArrayHandleBase<MaskTypes>;
|
||||
|
||||
public:
|
||||
using ThreadToOutputMapType = vtkm::cont::ArrayHandle<vtkm::Id>;
|
||||
|
||||
MaskSelect(const VariantArrayHandleMask& maskArray,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
this->ThreadToOutputMap = this->Build(maskArray, device);
|
||||
}
|
||||
|
||||
template <typename TypeList>
|
||||
MaskSelect(const vtkm::cont::VariantArrayHandleBase<TypeList>& indexArray,
|
||||
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
this->ThreadToOutputMap = this->Build(VariantArrayHandleMask(indexArray), device);
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
vtkm::Id GetThreadRange(RangeType vtkmNotUsed(outputRange)) const
|
||||
{
|
||||
return this->ThreadToOutputMap.GetNumberOfValues();
|
||||
}
|
||||
|
||||
template <typename RangeType>
|
||||
ThreadToOutputMapType GetThreadToOutputMap(RangeType vtkmNotUsed(outputRange)) const
|
||||
{
|
||||
return this->ThreadToOutputMap;
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadToOutputMapType ThreadToOutputMap;
|
||||
|
||||
VTKM_CONT ThreadToOutputMapType Build(const VariantArrayHandleMask& maskArray,
|
||||
vtkm::cont::DeviceAdapterId device);
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::worklet
|
||||
|
||||
#endif //vtk_m_worklet_MaskSelect_h
|
@ -163,20 +163,49 @@ public:
|
||||
/// Topology map worklets use topology map indices.
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename InputDomainType,
|
||||
typename G>
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesTopologyMap<InputDomainType> GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType& connectivity,
|
||||
const G& globalThreadIndexOffset) const
|
||||
vtkm::Id globalThreadIndexOffset) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesTopologyMap<InputDomainType>(threadIndex,
|
||||
outToIn.Get(outIndex),
|
||||
visit.Get(outIndex),
|
||||
outIndex,
|
||||
connectivity,
|
||||
globalThreadIndexOffset);
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesTopologyMap<InputDomainType> GetThreadIndices(
|
||||
const vtkm::Id3& threadIndex,
|
||||
const OutToInArrayType& vtkmNotUsed(outToIn),
|
||||
const VisitArrayType& vtkmNotUsed(visit),
|
||||
const ThreadToOutArrayType& vtkmNotUsed(threadToOut),
|
||||
const InputDomainType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0) const
|
||||
{
|
||||
using ScatterCheck = std::is_same<ScatterType, vtkm::worklet::ScatterIdentity>;
|
||||
VTKM_STATIC_ASSERT_MSG(ScatterCheck::value,
|
||||
"Scheduling on 3D topologies only works with default ScatterIdentity.");
|
||||
using MaskCheck = std::is_same<MaskType, vtkm::worklet::MaskNone>;
|
||||
VTKM_STATIC_ASSERT_MSG(MaskCheck::value,
|
||||
"Scheduling on 3D topologies only works with default MaskNone.");
|
||||
|
||||
return vtkm::exec::arg::ThreadIndicesTopologyMap<InputDomainType>(
|
||||
threadIndex, outToIn, visit, connectivity, globalThreadIndexOffset);
|
||||
threadIndex, connectivity, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -185,22 +185,51 @@ public:
|
||||
/// Point neighborhood worklets use the related thread indices class.
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename T,
|
||||
typename IndexType,
|
||||
typename OutToInArrayType,
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
vtkm::IdComponent Dimension>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesPointNeighborhood GetThreadIndices(
|
||||
const IndexType& threadIndex,
|
||||
vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const vtkm::exec::ConnectivityStructured<vtkm::TopologyElementTagCell,
|
||||
vtkm::TopologyElementTagPoint,
|
||||
Dimension>& inputDomain, //this should be explicitly
|
||||
const T& globalThreadIndexOffset = 0) const
|
||||
vtkm::Id globalThreadIndexOffset = 0) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesPointNeighborhood(threadIndex,
|
||||
outToIn.Get(outIndex),
|
||||
visit.Get(outIndex),
|
||||
outIndex,
|
||||
inputDomain,
|
||||
globalThreadIndexOffset);
|
||||
}
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesPointNeighborhood GetThreadIndices(
|
||||
const vtkm::Id3& threadIndex,
|
||||
const OutToInArrayType& vtkmNotUsed(outToIn),
|
||||
const VisitArrayType& vtkmNotUsed(visit),
|
||||
const ThreadToOutArrayType& vtkmNotUsed(threadToOut),
|
||||
const InputDomainType& connectivity,
|
||||
vtkm::Id globalThreadIndexOffset = 0) const
|
||||
{
|
||||
using ScatterCheck = std::is_same<ScatterType, vtkm::worklet::ScatterIdentity>;
|
||||
VTKM_STATIC_ASSERT_MSG(ScatterCheck::value,
|
||||
"Scheduling on 3D topologies only works with default ScatterIdentity.");
|
||||
using MaskCheck = std::is_same<MaskType, vtkm::worklet::MaskNone>;
|
||||
VTKM_STATIC_ASSERT_MSG(MaskCheck::value,
|
||||
"Scheduling on 3D topologies only works with default MaskNone.");
|
||||
|
||||
return vtkm::exec::arg::ThreadIndicesPointNeighborhood(
|
||||
threadIndex, outToIn, visit, inputDomain, globalThreadIndexOffset);
|
||||
threadIndex, connectivity, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -178,20 +178,23 @@ public:
|
||||
/// Reduce by key worklets use the related thread indices class.
|
||||
///
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
template <typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesReduceByKey GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
vtkm::Id threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType& inputDomain,
|
||||
const T& globalThreadIndexOffset = 0) const
|
||||
vtkm::Id globalThreadIndexOffset = 0) const
|
||||
{
|
||||
const vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesReduceByKey(threadIndex,
|
||||
outToIn.Get(threadIndex),
|
||||
visit.Get(threadIndex),
|
||||
outToIn.Get(outIndex),
|
||||
visit.Get(outIndex),
|
||||
outIndex,
|
||||
inputDomain,
|
||||
globalThreadIndexOffset);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ struct PointGradient : public vtkm::worklet::WorkletMapCellToPoint
|
||||
for (vtkm::IdComponent i = 0; i < numCells; ++i)
|
||||
{
|
||||
const vtkm::Id cellId = cellIds[i];
|
||||
CellThreadIndices cellIndices(cellId, cellId, 0, geometry);
|
||||
CellThreadIndices cellIndices(cellId, cellId, 0, cellId, geometry);
|
||||
|
||||
const CellShapeTag cellShape = cellIndices.GetCellShape();
|
||||
|
||||
|
@ -266,8 +266,9 @@ struct DispatcherBaseTryExecuteFunctor
|
||||
Invocation& invocation,
|
||||
const RangeType& dimensions)
|
||||
{
|
||||
auto outputRange = self->Scatter.GetOutputRange(dimensions);
|
||||
self->InvokeTransportParameters(
|
||||
invocation, dimensions, self->Scatter.GetOutputRange(dimensions), device);
|
||||
invocation, dimensions, outputRange, self->Mask.GetThreadRange(outputRange), device);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -659,6 +660,7 @@ public:
|
||||
//@}
|
||||
|
||||
using ScatterType = typename WorkletType::ScatterType;
|
||||
using MaskType = typename WorkletType::MaskType;
|
||||
|
||||
template <typename... Args>
|
||||
VTKM_CONT void Invoke(Args&&... args) const
|
||||
@ -670,10 +672,58 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType
|
||||
// or MapType, then that probably means that the worklet you are trying to execute has defined a
|
||||
// custom ScatterType or MaskType and that you need to create one (because there is no default
|
||||
// way to construct the scatter or mask).
|
||||
VTKM_CONT
|
||||
DispatcherBase(const WorkletType& worklet, const ScatterType& scatter)
|
||||
DispatcherBase(const WorkletType& worklet = WorkletType(),
|
||||
const ScatterType& scatter = ScatterType(),
|
||||
const MaskType& mask = MaskType())
|
||||
: Worklet(worklet)
|
||||
, Scatter(scatter)
|
||||
, Mask(mask)
|
||||
, Device(vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
}
|
||||
|
||||
// If you get a compile error here about there being no appropriate constructor for MaskType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// MaskType and that you need to create one (because there is no default way to construct the
|
||||
// mask).
|
||||
VTKM_CONT
|
||||
DispatcherBase(const ScatterType& scatter, const MaskType& mask = MaskType())
|
||||
: Worklet(WorkletType())
|
||||
, Scatter(scatter)
|
||||
, Mask(mask)
|
||||
, Device(vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
}
|
||||
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct the
|
||||
// scatter).
|
||||
VTKM_CONT
|
||||
DispatcherBase(const WorkletType& worklet,
|
||||
const MaskType& mask,
|
||||
const ScatterType& scatter = ScatterType())
|
||||
: Worklet(worklet)
|
||||
, Scatter(scatter)
|
||||
, Mask(mask)
|
||||
, Device(vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
}
|
||||
|
||||
// If you get a compile error here about there being no appropriate constructor for ScatterType,
|
||||
// then that probably means that the worklet you are trying to execute has defined a custom
|
||||
// ScatterType and that you need to create one (because there is no default way to construct the
|
||||
// scatter).
|
||||
VTKM_CONT
|
||||
DispatcherBase(const MaskType& mask, const ScatterType& scatter = ScatterType())
|
||||
: Worklet(WorkletType())
|
||||
, Scatter(scatter)
|
||||
, Mask(mask)
|
||||
, Device(vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
}
|
||||
@ -718,6 +768,7 @@ protected:
|
||||
|
||||
WorkletType Worklet;
|
||||
ScatterType Scatter;
|
||||
MaskType Mask;
|
||||
|
||||
private:
|
||||
// Dispatchers cannot be copied
|
||||
@ -729,10 +780,12 @@ private:
|
||||
template <typename Invocation,
|
||||
typename InputRangeType,
|
||||
typename OutputRangeType,
|
||||
typename ThreadRangeType,
|
||||
typename DeviceAdapter>
|
||||
VTKM_CONT void InvokeTransportParameters(Invocation& invocation,
|
||||
const InputRangeType& inputRange,
|
||||
OutputRangeType&& outputRange,
|
||||
ThreadRangeType&& threadRange,
|
||||
DeviceAdapter device) const
|
||||
{
|
||||
// The first step in invoking a worklet is to transport the arguments to
|
||||
@ -758,17 +811,21 @@ private:
|
||||
TransportFunctorType(invocation.GetInputDomain(), inputRange, outputRange));
|
||||
|
||||
// Get the arrays used for scattering input to output.
|
||||
typename WorkletType::ScatterType::OutputToInputMapType outputToInputMap =
|
||||
typename ScatterType::OutputToInputMapType outputToInputMap =
|
||||
this->Scatter.GetOutputToInputMap(inputRange);
|
||||
typename WorkletType::ScatterType::VisitArrayType visitArray =
|
||||
this->Scatter.GetVisitArray(inputRange);
|
||||
typename ScatterType::VisitArrayType visitArray = this->Scatter.GetVisitArray(inputRange);
|
||||
|
||||
// Get the arrays used for masking output elements.
|
||||
typename MaskType::ThreadToOutputMapType threadToOutputMap =
|
||||
this->Mask.GetThreadToOutputMap(inputRange);
|
||||
|
||||
// Replace the parameters in the invocation with the execution object and
|
||||
// pass to next step of Invoke. Also add the scatter information.
|
||||
this->InvokeSchedule(invocation.ChangeParameters(execObjectParameters)
|
||||
.ChangeOutputToInputMap(outputToInputMap.PrepareForInput(device))
|
||||
.ChangeVisitArray(visitArray.PrepareForInput(device)),
|
||||
outputRange,
|
||||
.ChangeVisitArray(visitArray.PrepareForInput(device))
|
||||
.ChangeThreadToOutputMap(threadToOutputMap.PrepareForInput(device)),
|
||||
threadRange,
|
||||
device);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <vtkm/cont/arg/TypeCheckTagCellSet.h>
|
||||
#include <vtkm/cont/arg/TypeCheckTagExecObject.h>
|
||||
|
||||
#include <vtkm/worklet/MaskNone.h>
|
||||
#include <vtkm/worklet/ScatterIdentity.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -129,6 +130,11 @@ public:
|
||||
/// identity scatter (1-to-1 input to output).
|
||||
using ScatterType = vtkm::worklet::ScatterIdentity;
|
||||
|
||||
/// All worklets must define their mask operation. The mask defines which
|
||||
/// outputs are generated. The default mask is the none mask, which generates
|
||||
/// everything in the output domain.
|
||||
using MaskType = vtkm::worklet::MaskNone;
|
||||
|
||||
/// \c ControlSignature tag for whole input arrays.
|
||||
///
|
||||
/// The \c WholeArrayIn control signature tag specifies an \c ArrayHandle
|
||||
@ -229,16 +235,19 @@ public:
|
||||
template <typename T,
|
||||
typename OutToInArrayType,
|
||||
typename VisitArrayType,
|
||||
typename ThreadToOutArrayType,
|
||||
typename InputDomainType>
|
||||
VTKM_EXEC vtkm::exec::arg::ThreadIndicesBasic GetThreadIndices(
|
||||
const T& threadIndex,
|
||||
const OutToInArrayType& outToIn,
|
||||
const VisitArrayType& visit,
|
||||
const ThreadToOutArrayType& threadToOut,
|
||||
const InputDomainType&,
|
||||
const T& globalThreadIndexOffset = 0) const
|
||||
{
|
||||
vtkm::Id outIndex = threadToOut.Get(threadIndex);
|
||||
return vtkm::exec::arg::ThreadIndicesBasic(
|
||||
threadIndex, outToIn.Get(threadIndex), visit.Get(threadIndex), globalThreadIndexOffset);
|
||||
threadIndex, outToIn.Get(outIndex), visit.Get(outIndex), outIndex, globalThreadIndexOffset);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -47,7 +47,9 @@ set(unit_tests
|
||||
UnitTestMagnitude.cxx
|
||||
UnitTestMarchingCubes.cxx
|
||||
UnitTestMask.cxx
|
||||
UnitTestMaskIndices.cxx
|
||||
UnitTestMaskPoints.cxx
|
||||
UnitTestMaskSelect.cxx
|
||||
UnitTestNormalize.cxx
|
||||
UnitTestNDimsEntropy.cxx
|
||||
UnitTestNDimsHistogram.cxx
|
||||
@ -59,6 +61,7 @@ set(unit_tests
|
||||
UnitTestProbe.cxx
|
||||
UnitTestRemoveUnusedPoints.cxx
|
||||
UnitTestScalarsToColors.cxx
|
||||
UnitTestScatterAndMask.cxx
|
||||
UnitTestScatterCounting.cxx
|
||||
UnitTestScatterPermutation.cxx
|
||||
UnitTestSplatKernels.cxx
|
||||
|
140
vtkm/worklet/testing/UnitTestMaskIndices.cxx
Normal file
140
vtkm/worklet/testing/UnitTestMaskIndices.cxx
Normal file
@ -0,0 +1,140 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
#include <vtkm/worklet/MaskIndices.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/WorkletMapTopology.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <random>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class Worklet : public vtkm::worklet::WorkletMapCellToPoint
|
||||
{
|
||||
public:
|
||||
using ControlSignature = void(CellSetIn cellset, FieldInOutPoint outPointId);
|
||||
using ExecutionSignature = void(InputIndex, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
using MaskType = vtkm::worklet::MaskIndices;
|
||||
|
||||
VTKM_EXEC void operator()(vtkm::Id pointId, vtkm::Id& outPointId) const { outPointId = pointId; }
|
||||
};
|
||||
|
||||
template <typename CellSetType>
|
||||
void RunTest(const CellSetType& cellset, const vtkm::cont::ArrayHandle<vtkm::Id>& indices)
|
||||
{
|
||||
vtkm::Id numPoints = cellset.GetNumberOfPoints();
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> outPointId;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant<vtkm::Id>(-1, numPoints), outPointId);
|
||||
|
||||
vtkm::worklet::DispatcherMapTopology<Worklet> dispatcher(vtkm::worklet::MaskIndices{ indices });
|
||||
dispatcher.Invoke(cellset, outPointId);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Int8> stencil;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant<vtkm::Int8>(0, numPoints), stencil);
|
||||
|
||||
// Check that output that should be written was.
|
||||
for (vtkm::Id i = 0; i < indices.GetNumberOfValues(); ++i)
|
||||
{
|
||||
// All unmasked indices should have been copied to the output.
|
||||
vtkm::Id unmaskedIndex = indices.GetPortalConstControl().Get(i);
|
||||
vtkm::Id writtenValue = outPointId.GetPortalConstControl().Get(unmaskedIndex);
|
||||
VTKM_TEST_ASSERT(unmaskedIndex == writtenValue,
|
||||
"Did not pass unmasked index. Expected ",
|
||||
unmaskedIndex,
|
||||
". Got ",
|
||||
writtenValue);
|
||||
|
||||
// Mark index as passed.
|
||||
stencil.GetPortalControl().Set(unmaskedIndex, 1);
|
||||
}
|
||||
|
||||
// Check that output that should not be written was not.
|
||||
for (vtkm::Id i = 0; i < numPoints; ++i)
|
||||
{
|
||||
if (stencil.GetPortalConstControl().Get(i) == 0)
|
||||
{
|
||||
vtkm::Id foundValue = outPointId.GetPortalConstControl().Get(i);
|
||||
VTKM_TEST_ASSERT(foundValue == -1,
|
||||
"Expected index ",
|
||||
i,
|
||||
" to be unwritten but was filled with ",
|
||||
foundValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestMaskIndices()
|
||||
{
|
||||
vtkm::cont::DataSet dataset = vtkm::cont::testing::MakeTestDataSet().Make2DUniformDataSet0();
|
||||
auto cellset = dataset.GetCellSet();
|
||||
vtkm::Id numberOfPoints = cellset.GetNumberOfPoints();
|
||||
|
||||
vtkm::UInt32 seed = static_cast<vtkm::UInt32>(std::time(nullptr));
|
||||
|
||||
std::default_random_engine generator;
|
||||
generator.seed(seed);
|
||||
std::uniform_int_distribution<vtkm::Id> countDistribution(1, 2 * numberOfPoints);
|
||||
std::uniform_int_distribution<vtkm::Id> ptidDistribution(0, numberOfPoints - 1);
|
||||
|
||||
const int iterations = 5;
|
||||
std::cout << "Testing with random indices " << iterations << " times\n";
|
||||
std::cout << "Seed: " << seed << std::endl;
|
||||
for (int i = 1; i <= iterations; ++i)
|
||||
{
|
||||
std::cout << "iteration: " << i << "\n";
|
||||
|
||||
vtkm::Id count = countDistribution(generator);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> indices;
|
||||
indices.Allocate(count);
|
||||
|
||||
// Note that it is possible that the same index will be written twice, which is generally
|
||||
// a bad idea with MaskIndices. However, the worklet will write the same value for each
|
||||
// instance, so we should still get the correct result.
|
||||
auto portal = indices.GetPortalControl();
|
||||
std::cout << "using indices:";
|
||||
for (vtkm::Id j = 0; j < count; ++j)
|
||||
{
|
||||
auto val = ptidDistribution(generator);
|
||||
std::cout << " " << val;
|
||||
portal.Set(j, val);
|
||||
}
|
||||
std::cout << "\n";
|
||||
|
||||
RunTest(cellset, indices);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestMaskIndices(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestMaskIndices, argc, argv);
|
||||
}
|
215
vtkm/worklet/testing/UnitTestMaskSelect.cxx
Normal file
215
vtkm/worklet/testing/UnitTestMaskSelect.cxx
Normal file
@ -0,0 +1,215 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <vtkm/worklet/MaskSelect.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
constexpr vtkm::Id nullValue = -2;
|
||||
|
||||
struct TestMaskArrays
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> SelectArray;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> ThreadToOutputMap;
|
||||
};
|
||||
|
||||
TestMaskArrays MakeMaskArraysShort()
|
||||
{
|
||||
const vtkm::Id selectArraySize = 18;
|
||||
const vtkm::IdComponent selectArray[selectArraySize] = { 1, 1, 0, 0, 0, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
||||
const vtkm::Id threadRange = 4;
|
||||
const vtkm::Id threadToOutputMap[threadRange] = { 0, 1, 6, 17 };
|
||||
|
||||
TestMaskArrays arrays;
|
||||
|
||||
// Need to copy arrays so that the data does not go out of scope.
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandle(selectArray, selectArraySize),
|
||||
arrays.SelectArray);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandle(threadToOutputMap, threadRange),
|
||||
arrays.ThreadToOutputMap);
|
||||
|
||||
return arrays;
|
||||
}
|
||||
|
||||
TestMaskArrays MakeMaskArraysLong()
|
||||
{
|
||||
const vtkm::Id selectArraySize = 16;
|
||||
const vtkm::IdComponent selectArray[selectArraySize] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
|
||||
};
|
||||
const vtkm::Id threadRange = 15;
|
||||
const vtkm::Id threadToOutputMap[threadRange] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15
|
||||
};
|
||||
|
||||
TestMaskArrays arrays;
|
||||
|
||||
// Need to copy arrays so that the data does not go out of scope.
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandle(selectArray, selectArraySize),
|
||||
arrays.SelectArray);
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandle(threadToOutputMap, threadRange),
|
||||
arrays.ThreadToOutputMap);
|
||||
|
||||
return arrays;
|
||||
}
|
||||
|
||||
TestMaskArrays MakeMaskArraysZero()
|
||||
{
|
||||
const vtkm::Id selectArraySize = 6;
|
||||
const vtkm::IdComponent selectArray[selectArraySize] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
TestMaskArrays arrays;
|
||||
|
||||
// Need to copy arrays so that the data does not go out of scope.
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandle(selectArray, selectArraySize),
|
||||
arrays.SelectArray);
|
||||
arrays.ThreadToOutputMap.Allocate(0);
|
||||
|
||||
return arrays;
|
||||
}
|
||||
|
||||
struct TestMaskSelectWorklet : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn inputIndices, FieldInOut copyIndices);
|
||||
using ExecutionSignature = void(_1, _2);
|
||||
|
||||
using MaskType = vtkm::worklet::MaskSelect;
|
||||
|
||||
VTKM_EXEC
|
||||
void operator()(vtkm::Id inputIndex, vtkm::Id& indexCopy) const { indexCopy = inputIndex; }
|
||||
};
|
||||
|
||||
template <typename T, typename SelectArrayType>
|
||||
void CompareArrays(vtkm::cont::ArrayHandle<T> array1,
|
||||
vtkm::cont::ArrayHandle<T> array2,
|
||||
const SelectArrayType& selectArray)
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(SelectArrayType);
|
||||
|
||||
auto portal1 = array1.GetPortalConstControl();
|
||||
auto portal2 = array2.GetPortalConstControl();
|
||||
auto selectPortal = selectArray.GetPortalConstControl();
|
||||
|
||||
VTKM_TEST_ASSERT(portal1.GetNumberOfValues() == portal2.GetNumberOfValues());
|
||||
VTKM_TEST_ASSERT(portal1.GetNumberOfValues() == selectArray.GetNumberOfValues());
|
||||
|
||||
for (vtkm::Id index = 0; index < portal1.GetNumberOfValues(); index++)
|
||||
{
|
||||
if (selectPortal.Get(index))
|
||||
{
|
||||
T value1 = portal1.Get(index);
|
||||
T value2 = portal2.Get(index);
|
||||
VTKM_TEST_ASSERT(
|
||||
value1 == value2, "Array values not equal (", index, ": ", value1, " ", value2, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
T value = portal2.Get(index);
|
||||
VTKM_TEST_ASSERT(value == nullValue, "Expected null value, got ", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CompareArrays(vtkm::cont::ArrayHandle<T> array1, vtkm::cont::ArrayHandle<T> array2)
|
||||
{
|
||||
CompareArrays(
|
||||
array1, array2, vtkm::cont::make_ArrayHandleConstant<bool>(true, array1.GetNumberOfValues()));
|
||||
}
|
||||
|
||||
// This unit test makes sure the ScatterCounting generates the correct map
|
||||
// and visit arrays.
|
||||
void TestMaskArrayGeneration(const TestMaskArrays& arrays)
|
||||
{
|
||||
std::cout << " Testing array generation" << std::endl;
|
||||
|
||||
vtkm::worklet::MaskSelect mask(arrays.SelectArray, vtkm::cont::DeviceAdapterTagAny());
|
||||
|
||||
vtkm::Id inputSize = arrays.SelectArray.GetNumberOfValues();
|
||||
|
||||
std::cout << " Checking thread to output map ";
|
||||
vtkm::cont::printSummary_ArrayHandle(mask.GetThreadToOutputMap(inputSize), std::cout);
|
||||
CompareArrays(arrays.ThreadToOutputMap, mask.GetThreadToOutputMap(inputSize));
|
||||
}
|
||||
|
||||
// This is more of an integration test that makes sure the scatter works with a
|
||||
// worklet invocation.
|
||||
void TestMaskWorklet(const TestMaskArrays& arrays)
|
||||
{
|
||||
std::cout << " Testing mask select in a worklet." << std::endl;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<TestMaskSelectWorklet> dispatcher(
|
||||
vtkm::worklet::MaskSelect(arrays.SelectArray));
|
||||
|
||||
vtkm::Id inputSize = arrays.SelectArray.GetNumberOfValues();
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> inputIndices;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(inputSize), inputIndices);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> selectIndexCopy;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(nullValue, inputSize),
|
||||
selectIndexCopy);
|
||||
|
||||
std::cout << " Invoke worklet" << std::endl;
|
||||
dispatcher.Invoke(inputIndices, selectIndexCopy);
|
||||
|
||||
std::cout << " Check copied indices." << std::endl;
|
||||
CompareArrays(inputIndices, selectIndexCopy, arrays.SelectArray);
|
||||
}
|
||||
|
||||
void TestMaskSelectWithArrays(const TestMaskArrays& arrays)
|
||||
{
|
||||
TestMaskArrayGeneration(arrays);
|
||||
TestMaskWorklet(arrays);
|
||||
}
|
||||
|
||||
void TestMaskSelect()
|
||||
{
|
||||
std::cout << "Testing arrays with output smaller than input." << std::endl;
|
||||
TestMaskSelectWithArrays(MakeMaskArraysShort());
|
||||
|
||||
std::cout << "Testing arrays with output larger than input." << std::endl;
|
||||
TestMaskSelectWithArrays(MakeMaskArraysLong());
|
||||
|
||||
std::cout << "Testing arrays with zero output." << std::endl;
|
||||
TestMaskSelectWithArrays(MakeMaskArraysZero());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestMaskSelect(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestMaskSelect, argc, argv);
|
||||
}
|
193
vtkm/worklet/testing/UnitTestScatterAndMask.cxx
Normal file
193
vtkm/worklet/testing/UnitTestScatterAndMask.cxx
Normal file
@ -0,0 +1,193 @@
|
||||
//=============================================================================
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
#include <vtkm/worklet/DispatcherPointNeighborhood.h>
|
||||
#include <vtkm/worklet/MaskIndices.h>
|
||||
#include <vtkm/worklet/ScatterUniform.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleConstant.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
|
||||
#include <vtkm/Math.h>
|
||||
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using FieldType = vtkm::Float32;
|
||||
#define FieldNull vtkm::Nan32()
|
||||
constexpr vtkm::IdComponent IdNull = -2;
|
||||
|
||||
struct FieldWorklet : vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(WholeCellSetIn<>, // Placeholder for interface consistency
|
||||
FieldIn inputField,
|
||||
FieldInOut fieldCopy,
|
||||
FieldInOut visitCopy);
|
||||
using ExecutionSignature = void(_2, VisitIndex, _3, _4);
|
||||
using InputDomain = _2;
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterUniform<2>;
|
||||
using MaskType = vtkm::worklet::MaskIndices;
|
||||
|
||||
VTKM_EXEC void operator()(FieldType inField,
|
||||
vtkm::IdComponent visitIndex,
|
||||
FieldType& fieldCopy,
|
||||
vtkm::IdComponent& visitCopy) const
|
||||
{
|
||||
fieldCopy = inField;
|
||||
visitCopy = visitIndex;
|
||||
}
|
||||
};
|
||||
|
||||
struct TopologyWorklet : vtkm::worklet::WorkletMapCellToPoint
|
||||
{
|
||||
using ControlSignature = void(CellSetIn,
|
||||
FieldInPoint inputField,
|
||||
FieldInOutPoint fieldCopy,
|
||||
FieldInOutPoint visitCopy);
|
||||
using ExecutionSignature = void(_2, VisitIndex, _3, _4);
|
||||
using InputDomain = _1;
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterUniform<2>;
|
||||
using MaskType = vtkm::worklet::MaskIndices;
|
||||
|
||||
VTKM_EXEC void operator()(FieldType inField,
|
||||
vtkm::IdComponent visitIndex,
|
||||
FieldType& fieldCopy,
|
||||
vtkm::IdComponent& visitCopy) const
|
||||
{
|
||||
fieldCopy = inField;
|
||||
visitCopy = visitIndex;
|
||||
}
|
||||
};
|
||||
|
||||
struct NeighborhoodWorklet : vtkm::worklet::WorkletPointNeighborhood
|
||||
{
|
||||
using ControlSignature = void(CellSetIn,
|
||||
FieldIn inputField,
|
||||
FieldInOut fieldCopy,
|
||||
FieldInOut visitCopy);
|
||||
using ExecutionSignature = void(_2, VisitIndex, _3, _4);
|
||||
using InputDomain = _1;
|
||||
|
||||
using ScatterType = vtkm::worklet::ScatterUniform<2>;
|
||||
using MaskType = vtkm::worklet::MaskIndices;
|
||||
|
||||
VTKM_EXEC void operator()(FieldType inField,
|
||||
vtkm::IdComponent visitIndex,
|
||||
FieldType& fieldCopy,
|
||||
vtkm::IdComponent& visitCopy) const
|
||||
{
|
||||
fieldCopy = inField;
|
||||
visitCopy = visitIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename DispatcherType>
|
||||
void TestMapWorklet()
|
||||
{
|
||||
vtkm::cont::testing::MakeTestDataSet builder;
|
||||
vtkm::cont::DataSet data = builder.Make3DUniformDataSet1();
|
||||
|
||||
vtkm::cont::CellSetStructured<3> cellSet =
|
||||
data.GetCellSet().Cast<vtkm::cont::CellSetStructured<3>>();
|
||||
vtkm::Id numPoints = cellSet.GetNumberOfPoints();
|
||||
|
||||
vtkm::cont::ArrayHandle<FieldType> inField;
|
||||
inField.Allocate(numPoints);
|
||||
SetPortal(inField.GetPortalControl());
|
||||
|
||||
vtkm::cont::ArrayHandle<FieldType> fieldCopy;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(FieldNull, numPoints * 2), fieldCopy);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> visitCopy;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(IdNull, numPoints * 2), visitCopy);
|
||||
|
||||
// The scatter is hardcoded to create 2 outputs for every input.
|
||||
// Set up the mask to select a range of values in the middle.
|
||||
vtkm::Id maskStart = numPoints / 2;
|
||||
vtkm::Id maskEnd = (numPoints * 2) / 3;
|
||||
vtkm::worklet::MaskIndices mask(
|
||||
vtkm::cont::make_ArrayHandleCounting(maskStart, vtkm::Id(1), maskEnd - maskStart));
|
||||
|
||||
DispatcherType dispatcher(mask);
|
||||
dispatcher.Invoke(cellSet, inField, fieldCopy, visitCopy);
|
||||
|
||||
// Check outputs
|
||||
auto fieldCopyPortal = fieldCopy.GetPortalConstControl();
|
||||
auto visitCopyPortal = visitCopy.GetPortalConstControl();
|
||||
for (vtkm::Id outputIndex = 0; outputIndex < numPoints * 2; ++outputIndex)
|
||||
{
|
||||
FieldType fieldValue = fieldCopyPortal.Get(outputIndex);
|
||||
vtkm::IdComponent visitValue = visitCopyPortal.Get(outputIndex);
|
||||
if ((outputIndex >= maskStart) && (outputIndex < maskEnd))
|
||||
{
|
||||
vtkm::Id inputIndex = outputIndex / 2;
|
||||
FieldType expectedField = TestValue(inputIndex, FieldType());
|
||||
VTKM_TEST_ASSERT(fieldValue == expectedField,
|
||||
outputIndex,
|
||||
": expected ",
|
||||
expectedField,
|
||||
", got ",
|
||||
fieldValue);
|
||||
|
||||
vtkm::IdComponent expectedVisit = static_cast<vtkm::IdComponent>(outputIndex % 2);
|
||||
VTKM_TEST_ASSERT(visitValue == expectedVisit,
|
||||
outputIndex,
|
||||
": expected ",
|
||||
expectedVisit,
|
||||
", got ",
|
||||
visitValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
VTKM_TEST_ASSERT(vtkm::IsNan(fieldValue), outputIndex, ": expected NaN, got ", fieldValue);
|
||||
VTKM_TEST_ASSERT(
|
||||
visitValue == IdNull, outputIndex, ": expected ", IdNull, ", got ", visitValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Test()
|
||||
{
|
||||
std::cout << "Try on WorkletMapField" << std::endl;
|
||||
TestMapWorklet<vtkm::worklet::DispatcherMapField<FieldWorklet>>();
|
||||
|
||||
std::cout << "Try on WorkletMapCellToPoint" << std::endl;
|
||||
TestMapWorklet<vtkm::worklet::DispatcherMapTopology<TopologyWorklet>>();
|
||||
|
||||
std::cout << "Try on WorkletPointNeighborhood" << std::endl;
|
||||
TestMapWorklet<vtkm::worklet::DispatcherPointNeighborhood<NeighborhoodWorklet>>();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestScatterAndMask(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user