Commit bddad9b3 authored by Kenneth Moreland's avatar Kenneth Moreland

Remove TryExecute from filters

Now that the dispatcher does its own TryExecute, filters do not need to
do that. This change requires all worklets called by filters to be able
to execute without knowing the device a priori.
parent 03e2e721
......@@ -698,7 +698,7 @@ private:
template <typename Value>
struct BenchStableSortIndices
{
using SSI = vtkm::worklet::StableSortIndices<DeviceAdapterTag>;
using SSI = vtkm::worklet::StableSortIndices;
using ValueArrayHandle = vtkm::cont::ArrayHandle<Value, StorageTag>;
ValueArrayHandle ValueHandle;
......@@ -743,7 +743,7 @@ private:
template <typename Value>
struct BenchStableSortIndicesUnique
{
using SSI = vtkm::worklet::StableSortIndices<DeviceAdapterTag>;
using SSI = vtkm::worklet::StableSortIndices;
using IndexArrayHandle = typename SSI::IndexArrayType;
using ValueArrayHandle = vtkm::cont::ArrayHandle<Value, StorageTag>;
......@@ -915,6 +915,7 @@ public:
static VTKM_CONT int Run()
{
std::cout << DIVIDER << "\nRunning DeviceAdapter benchmarks\n";
vtkm::cont::GetGlobalRuntimeDeviceTracker().ForceDevice(DeviceAdapterTag());
// Run fixed bytes / size tests:
for (int sizeType = 0; sizeType < 2; ++sizeType)
......
......@@ -19,7 +19,6 @@
//============================================================================
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/io/writer/VTKDataSetWriter.h>
......@@ -37,7 +36,6 @@ using FloatVec3 = vtkm::Vec<vtkm::Float32, 3>;
namespace
{
template <typename DeviceTag>
struct FieldMapper
{
vtkm::cont::DynamicArrayHandle& Output;
......@@ -58,11 +56,11 @@ struct FieldMapper
{
if (this->IsCellField)
{
this->Output = this->Worklet.ProcessCellField(input, DeviceTag());
this->Output = this->Worklet.ProcessCellField(input);
}
else
{
this->Output = this->Worklet.ProcessPointField(input, DeviceTag());
this->Output = this->Worklet.ProcessPointField(input);
}
}
};
......@@ -79,10 +77,6 @@ int main(int argc, char* argv[])
return 1;
}
using DeviceAdapter = VTKM_DEFAULT_DEVICE_ADAPTER_TAG;
std::cout << "Device Adapter Name: " << vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName()
<< std::endl;
vtkm::io::reader::VTKDataSetReader reader(argv[1]);
vtkm::cont::DataSet input = reader.ReadDataSet();
......@@ -91,15 +85,14 @@ int main(int argc, char* argv[])
vtkm::Float32 clipValue = std::stof(argv[argc - 2]);
vtkm::worklet::Clip clip;
vtkm::cont::Timer<DeviceAdapter> total;
vtkm::cont::Timer<DeviceAdapter> timer;
vtkm::cont::Timer<> total;
vtkm::cont::Timer<> timer;
bool invertClip = false;
vtkm::cont::CellSetExplicit<> outputCellSet =
clip.Run(input.GetCellSet(0),
scalarField.GetData().ResetTypeList(vtkm::TypeListTagScalarAll()),
clipValue,
invertClip,
DeviceAdapter());
invertClip);
vtkm::Float64 clipTime = timer.GetElapsedTime();
vtkm::cont::DataSet output;
......@@ -108,7 +101,7 @@ int main(int argc, char* argv[])
auto inCoords = input.GetCoordinateSystem(0).GetData();
timer.Reset();
auto outCoords = clip.ProcessCellField(inCoords, DeviceAdapter());
auto outCoords = clip.ProcessCellField(inCoords);
vtkm::Float64 processCoordinatesTime = timer.GetElapsedTime();
output.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", outCoords));
......@@ -132,7 +125,7 @@ int main(int argc, char* argv[])
}
vtkm::cont::DynamicArrayHandle outField;
FieldMapper<DeviceAdapter> fieldMapper(outField, clip, isCellField);
FieldMapper fieldMapper(outField, clip, isCellField);
inField.GetData().CastAndCall(fieldMapper);
output.AddField(vtkm::cont::Field(inField.GetName(), inField.GetAssociation(), outField));
}
......
......@@ -62,10 +62,6 @@
#define DEBUG_TIMING
#ifndef VTKM_DEVICE_ADAPTER
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif
#ifdef ENABLE_SET_NUM_THREADS
#include "tbb/task_scheduler_init.h"
#endif
......@@ -149,12 +145,8 @@ private:
// Compute and render an isosurface for a uniform grid example
int main(int argc, char* argv[])
{
typedef VTKM_DEFAULT_DEVICE_ADAPTER_TAG DeviceAdapter;
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
tracker.ForceDevice(DeviceAdapter());
vtkm::cont::Timer<DeviceAdapter> totalTime;
// TODO: Change timing to use logging in vtkm/cont/Logging.h
vtkm::cont::Timer<> totalTime;
vtkm::Float64 prevTime = 0;
vtkm::Float64 currTime = 0;
std::cout << "ContourTreePPP2Mesh <options> <fileName>" << std::endl;
......@@ -337,20 +329,20 @@ int main(int argc, char* argv[])
////////////////////////////////////////////
if (computeBranchDecomposition)
{
vtkm::cont::Timer<DeviceAdapter> branchDecompTimer;
// TODO: Change timing to use logging in vtkm/cont/Logging.h
vtkm::cont::Timer<> branchDecompTimer;
// compute the volume for each hyperarc and superarc
cppp2_ns::IdArrayType superarcIntrinsicWeight;
cppp2_ns::IdArrayType superarcDependentWeight;
cppp2_ns::IdArrayType supernodeTransferWeight;
cppp2_ns::IdArrayType hyperarcDependentWeight;
cppp2_ns::ProcessContourTree::ComputeVolumeWeights<DeviceAdapter>(
filter.GetContourTree(),
filter.GetNumIterations(),
superarcIntrinsicWeight, // (output)
superarcDependentWeight, // (output)
supernodeTransferWeight, // (output)
hyperarcDependentWeight); // (output)
cppp2_ns::ProcessContourTree::ComputeVolumeWeights(filter.GetContourTree(),
filter.GetNumIterations(),
superarcIntrinsicWeight, // (output)
superarcDependentWeight, // (output)
supernodeTransferWeight, // (output)
hyperarcDependentWeight); // (output)
std::cout << std::setw(42) << std::left << "Compute Volume Weights"
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
branchDecompTimer.Reset();
......@@ -362,15 +354,14 @@ int main(int argc, char* argv[])
cppp2_ns::IdArrayType branchSaddle;
cppp2_ns::IdArrayType branchParent;
cppp2_ns::ProcessContourTree::ComputeVolumeBranchDecomposition<DeviceAdapter>(
filter.GetContourTree(),
superarcDependentWeight,
superarcIntrinsicWeight,
whichBranch, // (output)
branchMinimum, // (output)
branchMaximum, // (output)
branchSaddle, // (output)
branchParent); // (output)
cppp2_ns::ProcessContourTree::ComputeVolumeBranchDecomposition(filter.GetContourTree(),
superarcDependentWeight,
superarcIntrinsicWeight,
whichBranch, // (output)
branchMinimum, // (output)
branchMaximum, // (output)
branchSaddle, // (output)
branchParent); // (output)
std::cout << std::setw(42) << std::left << "Compute Volume Branch Decomposition"
<< ": " << branchDecompTimer.GetElapsedTime() << " seconds" << std::endl;
}
......@@ -388,7 +379,7 @@ int main(int argc, char* argv[])
std::cout << "Contour Tree" << std::endl;
std::cout << "============" << std::endl;
cppp2_ns::EdgePairArray saddlePeak;
cppp2_ns::ProcessContourTree::CollectSortedSuperarcs<DeviceAdapter>(
cppp2_ns::ProcessContourTree::CollectSortedSuperarcs(
filter.GetContourTree(), filter.GetSortOrder(), saddlePeak);
cppp2_ns::printEdgePairArray(saddlePeak);
}
......
......@@ -122,23 +122,12 @@ struct UpdateLifeState : public vtkm::worklet::WorkletPointNeighborhood3x3x3
class GameOfLife : public vtkm::filter::FilterDataSet<GameOfLife>
{
bool PrintedDeviceMsg = false;
public:
template <typename Policy, typename Device>
template <typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<Policy> policy,
Device)
vtkm::filter::PolicyBase<Policy> policy)
{
if (!this->PrintedDeviceMsg)
{
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<Device>;
std::cout << "Running GameOfLife filter on device adapter: " << DeviceAdapterTraits::GetName()
<< std::endl;
this->PrintedDeviceMsg = true;
}
using DispatcherType = vtkm::worklet::DispatcherPointNeighborhood<UpdateLifeState>;
......@@ -154,7 +143,6 @@ public:
//Update the game state
DispatcherType dispatcher;
dispatcher.SetDevice(Device());
dispatcher.Invoke(vtkm::filter::ApplyPolicy(cells, policy), prevstate, state, colors);
//save the results
......@@ -171,12 +159,11 @@ public:
return output;
}
template <typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT bool DoMapField(vtkm::cont::DataSet&,
const vtkm::cont::ArrayHandle<T, StorageType>&,
const vtkm::filter::FieldMetadata&,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
DeviceAdapter)
vtkm::filter::PolicyBase<DerivedPolicy>)
{
return false;
}
......
......@@ -28,7 +28,7 @@
#include <thread>
using RuntimeTaskQueue = TaskQueue<std::function<void(const vtkm::cont::RuntimeDeviceTracker&)>>;
using RuntimeTaskQueue = TaskQueue<std::function<void()>>;
/// \brief Construct a MultiDeviceGradient for a given multiblock dataset
///
......
......@@ -45,10 +45,10 @@ void process_block_tbb(RuntimeTaskQueue& queue)
{
//Step 1. Set the device adapter to this thread to TBB.
//This makes sure that any vtkm::filters used by our
//task operate only on TBB
//task operate only on TBB. The "global" thread tracker
//is actually thread-local, so we can use that.
//
vtkm::cont::RuntimeDeviceTracker tracker;
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagTBB{});
vtkm::cont::GetGlobalRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagTBB{});
while (queue.hasTasks())
{
......@@ -60,7 +60,7 @@ void process_block_tbb(RuntimeTaskQueue& queue)
//when the queue is empty and we are shutting down
if (task != nullptr)
{
task(tracker);
task();
}
//Step 4. Notify the queue that we finished processing this task
......@@ -73,13 +73,10 @@ void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
{
//Step 1. Set the device adapter to this thread to cuda.
//This makes sure that any vtkm::filters used by our
//task operate only on cuda
//task operate only on cuda. The "global" thread tracker
//is actually thread-local, so we can use that.
//
vtkm::cont::RuntimeDeviceTracker tracker;
#if defined(VTKM_ENABLE_CUDA)
auto error = cudaSetDevice(gpuId);
tracker.ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
#endif
vtkm::cont::GetGlobalRuntimeDeviceTracker().ForceDevice(vtkm::cont::DeviceAdapterTagCuda{});
(void)gpuId;
while (queue.hasTasks())
......@@ -87,12 +84,12 @@ void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
//Step 2. Get the task to run on cuda
auto task = queue.pop();
//Step 3. Run the task on TBB. We check the validity
//Step 3. Run the task on cuda. We check the validity
//of the task since we could be given an empty task
//when the queue is empty and we are shutting down
if (task != nullptr)
{
task(tracker);
task();
}
//Step 4. Notify the queue that we finished processing this task
......@@ -190,11 +187,8 @@ inline VTKM_CONT vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution
{
vtkm::cont::DataSet input = *block;
this->Queue.push( //build a lambda that is the work to do
[=](const vtkm::cont::RuntimeDeviceTracker& tracker) {
//make a per thread copy of the filter
//and give it the device tracker
[=]() {
vtkm::filter::Gradient perThreadGrad = gradient;
perThreadGrad.SetRuntimeDeviceTracker(tracker);
vtkm::cont::DataSet result = perThreadGrad.Execute(input, policy);
outPtr->ReplaceBlock(0, result);
......@@ -212,11 +206,8 @@ inline VTKM_CONT vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution
//will allows us to have multiple works execute in a non
//blocking manner
this->Queue.push( //build a lambda that is the work to do
[=](const vtkm::cont::RuntimeDeviceTracker& tracker) {
//make a per thread copy of the filter
//and give it the device tracker
[=]() {
vtkm::filter::Gradient perThreadGrad = gradient;
perThreadGrad.SetRuntimeDeviceTracker(tracker);
vtkm::cont::DataSet result = perThreadGrad.Execute(input, policy);
outPtr->ReplaceBlock(index, result);
......
......@@ -18,10 +18,6 @@
// this software.
//============================================================================
#ifndef VTKM_DEVICE_ADAPTER
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif
#include <vtkm/cont/DataSet.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/GridEvaluators.h>
......@@ -66,8 +62,6 @@ void RunTest(const std::string& fname,
vtkm::Id advectType,
vtkm::Id seeding)
{
using DeviceAdapter = VTKM_DEFAULT_DEVICE_ADAPTER_TAG;
using FieldType = vtkm::Float32;
using FieldHandle = vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>>;
......@@ -163,12 +157,12 @@ void RunTest(const std::string& fname,
if (advectType == 0)
{
vtkm::worklet::ParticleAdvection particleAdvection;
particleAdvection.Run(rk4, seedArray, numSteps, DeviceAdapter());
particleAdvection.Run(rk4, seedArray, numSteps);
}
else
{
vtkm::worklet::Streamline streamline;
streamline.Run(rk4, seedArray, numSteps, DeviceAdapter());
streamline.Run(rk4, seedArray, numSteps);
}
auto t1 = std::chrono::high_resolution_clock::now() - t0;
......
......@@ -18,10 +18,6 @@
// this software.
//============================================================================
#ifndef VTKM_DEVICE_ADAPTER
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_SERIAL
#endif
#include <vtkm/cont/DataSet.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/Integrators.h>
......@@ -49,7 +45,6 @@ int renderAndWriteDataSet(const vtkm::cont::DataSet& dataset)
void RunTest(vtkm::Id numSteps, vtkm::Float32 stepSize, vtkm::Id advectType)
{
using DeviceAdapter = VTKM_DEFAULT_DEVICE_ADAPTER_TAG;
using FieldType = vtkm::Float32;
using FieldHandle = vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>>;
......@@ -104,13 +99,12 @@ void RunTest(vtkm::Id numSteps, vtkm::Float32 stepSize, vtkm::Id advectType)
if (advectType == 0)
{
vtkm::worklet::ParticleAdvection particleAdvection;
particleAdvection.Run(integrator, seedArray, numSteps, DeviceAdapter());
particleAdvection.Run(integrator, seedArray, numSteps);
}
else
{
vtkm::worklet::Streamline streamline;
vtkm::worklet::StreamlineResult res =
streamline.Run(integrator, seedArray, numSteps, DeviceAdapter());
vtkm::worklet::StreamlineResult res = streamline.Run(integrator, seedArray, numSteps);
vtkm::cont::DataSet outData;
vtkm::cont::CoordinateSystem outputCoords("coordinates", res.positions);
outData.AddCellSet(res.polyLines);
......
......@@ -202,10 +202,6 @@ template <typename T>
struct ScanExclusiveFunctor
{
T result;
ScanExclusiveFunctor()
: result(T(0))
{
}
template <typename Device, typename... Args>
VTKM_CONT bool operator()(Device, Args&&... args)
......
......@@ -53,9 +53,11 @@ public:
/// Builds the cell locator lookup structure
///
template <typename DeviceAdapter, typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(DeviceAdapter device, CellSetList cellSetTypes = CellSetList())
template <typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(CellSetList cellSetTypes = CellSetList())
{
VTKM_IS_LIST_TAG(CellSetList);
if (IsUniformGrid(this->CellSet, this->Coordinates))
{
// nothing to build for uniform grid
......@@ -64,7 +66,7 @@ public:
{
this->Locator.SetCellSet(this->CellSet);
this->Locator.SetCoordinates(this->Coordinates);
this->Locator.Build(device, cellSetTypes);
this->Locator.Build(cellSetTypes);
}
}
......@@ -124,13 +126,11 @@ public:
///
template <typename PointComponentType,
typename PointStorageType,
typename DeviceAdapter,
typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void FindCells(
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& points,
vtkm::cont::ArrayHandle<vtkm::Id>& cellIds,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>>& parametricCoords,
DeviceAdapter device,
CellSetList cellSetTypes = CellSetList()) const
{
if (IsUniformGrid(this->CellSet, this->Coordinates))
......@@ -139,12 +139,11 @@ public:
this->Coordinates.GetData().Cast<vtkm::cont::ArrayHandleUniformPointCoordinates>();
auto cellset = this->CellSet.ResetCellSetList(StructuredCellSetList());
vtkm::worklet::DispatcherMapField<FindCellWorklet> dispatcher;
dispatcher.SetDevice(DeviceAdapter());
dispatcher.Invoke(points, cellset, coordinates, cellIds, parametricCoords);
}
else
{
this->Locator.FindCells(points, cellIds, parametricCoords, device, cellSetTypes);
this->Locator.FindCells(points, cellIds, parametricCoords, cellSetTypes);
}
}
......
......@@ -20,11 +20,12 @@
#ifndef vtk_m_cont_CellLocatorTwoLevelUniformGrid_h
#define vtk_m_cont_CellLocatorTwoLevelUniformGrid_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/exec/internal/TwoLevelUniformGridExecutionObject.h>
......@@ -483,11 +484,12 @@ public:
/// Builds the cell locator lookup structure
///
template <typename DeviceAdapter, typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(DeviceAdapter, CellSetList cellSetTypes = CellSetList())
template <typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(CellSetList cellSetTypes = CellSetList())
{
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
vtkm::worklet::Invoker invoke(DeviceAdapter{});
VTKM_IS_LIST_TAG(CellSetList);
vtkm::worklet::Invoker invoke;
auto cellset = this->CellSet.ResetCellSetList(cellSetTypes);
const auto& coords = this->Coordinates;
......@@ -516,7 +518,7 @@ public:
invoke(countL1, cellset, coords, binCounts);
// 3: Total number of unique (cell, bin) pairs (for pre-allocating arrays)
vtkm::Id numPairsL1 = Algorithm::ScanExclusive(binCounts, binCounts);
vtkm::Id numPairsL1 = vtkm::cont::Algorithm::ScanExclusive(binCounts, binCounts);
// 4: For each cell find the top level bins that intersect it
vtkm::cont::ArrayHandle<vtkm::Id> binIds;
......@@ -526,28 +528,29 @@ public:
binCounts.ReleaseResources();
// 5: From above, find the number of cells that intersect each top level bin
Algorithm::Sort(binIds);
vtkm::cont::Algorithm::Sort(binIds);
vtkm::cont::ArrayHandle<vtkm::Id> bins;
vtkm::cont::ArrayHandle<vtkm::Id> cellsPerBin;
Algorithm::ReduceByKey(binIds,
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(1), numPairsL1),
bins,
cellsPerBin,
vtkm::Sum());
vtkm::cont::Algorithm::ReduceByKey(
binIds,
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(1), numPairsL1),
bins,
cellsPerBin,
vtkm::Sum());
binIds.ReleaseResources();
// 6: Compute level-2 dimensions
vtkm::Id numberOfBins =
ls.TopLevel.Dimensions[0] * ls.TopLevel.Dimensions[1] * ls.TopLevel.Dimensions[2];
Algorithm::Copy(vtkm::cont::make_ArrayHandleConstant(DimVec3(0), numberOfBins),
ls.LeafDimensions);
vtkm::cont::ArrayCopy(vtkm::cont::make_ArrayHandleConstant(DimVec3(0), numberOfBins),
ls.LeafDimensions);
GenerateBinsL1 generateL1(ls.TopLevel.BinSize, this->DensityL2);
invoke(generateL1, bins, cellsPerBin, ls.LeafDimensions);
bins.ReleaseResources();
cellsPerBin.ReleaseResources();
// 7: Compute number of level-2 bins
vtkm::Id numberOfLeaves = Algorithm::ScanExclusive(
vtkm::Id numberOfLeaves = vtkm::cont::Algorithm::ScanExclusive(
vtkm::cont::make_ArrayHandleTransform(ls.LeafDimensions, DimensionsToCount()),
ls.LeafStartIndex);
......@@ -557,7 +560,7 @@ public:
invoke(countL2, cellset, coords, ls.LeafDimensions, binCounts);
// 9: Total number of unique (cell, bin) pairs (for pre-allocating arrays)
vtkm::Id numPairsL2 = Algorithm::ScanExclusive(binCounts, binCounts);
vtkm::Id numPairsL2 = vtkm::cont::Algorithm::ScanExclusive(binCounts, binCounts);
// 10: For each cell, find the l2 bins they intersect
binIds.Allocate(numPairsL2);
......@@ -568,21 +571,23 @@ public:
binCounts.ReleaseResources();
// 11: From above, find the cells that each l2 bin intersects
Algorithm::SortByKey(binIds, ls.CellIds);
Algorithm::ReduceByKey(binIds,
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(1), numPairsL2),
bins,
cellsPerBin,
vtkm::Sum());
vtkm::cont::Algorithm::SortByKey(binIds, ls.CellIds);
vtkm::cont::Algorithm::ReduceByKey(
binIds,
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(1), numPairsL2),
bins,
cellsPerBin,
vtkm::Sum());
binIds.ReleaseResources();
// 12: Generate the leaf bin arrays
vtkm::cont::ArrayHandle<vtkm::Id> cellsStart;
Algorithm::ScanExclusive(cellsPerBin, cellsStart);
vtkm::cont::Algorithm::ScanExclusive(cellsPerBin, cellsStart);
Algorithm::Copy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numberOfLeaves),
ls.CellStartIndex);
Algorithm::Copy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numberOfLeaves), ls.CellCount);
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numberOfLeaves),
ls.CellStartIndex);
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, numberOfLeaves),
ls.CellCount);
invoke(GenerateBinsL2{}, bins, cellsStart, cellsPerBin, ls.CellStartIndex, ls.CellCount);
std::swap(this->LookupStructure, ls);
......@@ -694,17 +699,14 @@ public:
///
template <typename PointComponentType,
typename PointStorageType,
typename DeviceAdapter,
typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void FindCells(
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& points,
vtkm::cont::ArrayHandle<vtkm::Id>& cellIds,
vtkm::cont::ArrayHandle<FloatVec3>& parametricCoords,
DeviceAdapter,
CellSetList cellSetTypes = CellSetList()) const
{
vtkm::worklet::DispatcherMapField<FindCellWorklet> dispatcher;
dispatcher.SetDevice(DeviceAdapter());
dispatcher.Invoke(points,
this->CellSet.ResetCellSetList(cellSetTypes),
this->Coordinates,
......
......@@ -72,6 +72,73 @@ VTKM_CONT ImplicitFunctionHandle make_ImplicitFunctionHandle(Args&&... args)
return ImplicitFunctionHandle(
new ImplicitFunctionType(std::forward<Args>(args)...), true, DeviceAdapterList());
}
//============================================================================
/// A helpful wrapper that returns a functor that calls the (virtual) value method of a given
/// ImplicitFunction. Can be passed to things that expect a functor instead of an ImplictFunction
/// class (like an array transform).
///
class VTKM_ALWAYS_EXPORT ImplicitFunctionValueHandle
: public vtkm::cont::ExecutionAndControlObjectBase
{
vtkm::cont::ImplicitFunctionHandle Handle;
public:
ImplicitFunctionValueHandle() = default;
ImplicitFunctionValueHandle(const ImplicitFunctionHandle& handle)
: Handle(handle)
{
}
template <typename ImplicitFunctionType,
typename DeviceAdapterList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG>
explicit ImplicitFunctionValueHandle(ImplicitFunctionType* function,
bool acquireOwnership = true,
DeviceAdapterList devices = DeviceAdapterList())
: Handle(function, acquireOwnership, devices)
{
}
VTKM_CONT const vtkm::cont::ImplicitFunctionHandle& GetHandle() const {