Add vtkm::exec::TaskBase, and rename WorkletInvokeFunctor to TaskSingular

Previously WorkletInvokeFunctor inherited from vtkm::exec::FunctorBase,
which is also the base class for all users Worklets and for all functors
based to DeviceAdapter::Schedule.

This is done for a few reasons. The first is that we reduce the
minimum size of user worklets. Previously the users worklet would hold
a reference to the error message, and so would the wrapper class added
when calling DeviceAdapter::Schedule. Now we only have the users worklet
holding a reference.

Second, by refactoring to have two base classes we can better improve
the documentation on what responsibilities FunctorBase.h has, compared
to TaskBase.
This commit is contained in:
Robert Maynard 2017-05-01 15:19:42 -04:00
parent e9898cc5cf
commit 022c36fa4f
13 changed files with 395 additions and 162 deletions

@ -36,7 +36,7 @@
#include <vtkm/exec/cuda/internal/WrappedOperators.h>
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <vtkm/exec/internal/TaskSingular.h>

@ -33,6 +33,7 @@ set(headers
ImplicitFunction.h
Jacobian.h
ParametricCoordinates.h
TaskBase.h
)
#-----------------------------------------------------------------------------

@ -24,12 +24,15 @@
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
#include <vtkm/cont/vtkm_cont_export.h>
namespace vtkm {
namespace exec {
/// Base class for all functors invoked in the execution environment from a
/// call to vtkm::cont::DeviceAdapterAlgorithm::Schedule. Subclasses must
/// implement operator() const with an index argument.
/// Base class for all user worklets invoked in the execution environment from a
/// call to vtkm::cont::DeviceAdapterAlgorithm::Schedule.
///
/// This class contains a public method named RaiseError that can be called in
/// the execution environment to signal a problem.
@ -56,7 +59,6 @@ public:
{
this->ErrorMessage = buffer;
}
private:
vtkm::exec::internal::ErrorMessageBuffer ErrorMessage;
};

42
vtkm/exec/TaskBase.h Normal file

@ -0,0 +1,42 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// 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_exec_TaskBase_h
#define vtk_m_exec_TaskBase_h
#include <vtkm/Types.h>
#include <vtkm/exec/internal/ErrorMessageBuffer.h>
namespace vtkm {
namespace exec {
/// Base class for all classes that are used to marshal data from the invocation
/// parameters to the user worklets when invoked in the execution environment.
/// These classes are generally automatically created by
/// vtkm::worklet::internal::DispatcherBase.
class TaskBase
{
};
}
} // namespace vtkm::exec
#endif //vtk_m_exec_TaskBase_h

@ -21,7 +21,7 @@
set(headers
ErrorMessageBuffer.h
ReduceByKeyLookup.h
WorkletInvokeFunctor.h
TaskSingular.h
WorkletInvokeFunctorDetail.h
)

@ -17,15 +17,16 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_exec_internal_WorkletInvokeFunctor_h
#define vtk_m_exec_internal_WorkletInvokeFunctor_h
#ifndef vtk_m_exec_internal_TaskSingular_h
#define vtk_m_exec_internal_TaskSingular_h
#include <vtkm/internal/Invocation.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/exec/TaskBase.h>
#include <vtkm/exec/arg/Fetch.h>
//Todo: rename this header to TaskSingularDetail.h
#include <vtkm/exec/internal/WorkletInvokeFunctorDetail.h>
namespace vtkm {
@ -33,28 +34,26 @@ namespace exec {
namespace internal {
template<typename WorkletType, typename InvocationType>
class WorkletInvokeFunctor : public vtkm::exec::FunctorBase
class TaskSingular : public vtkm::exec::TaskBase
{
public:
VTKM_CONT
WorkletInvokeFunctor(const WorkletType &worklet,
TaskSingular(const WorkletType &worklet,
const InvocationType &invocation,
const vtkm::Id &globalIndexOffset=0)
: Worklet(worklet), Invocation(invocation), GlobalIndexOffset(globalIndexOffset) { }
VTKM_CONT
void SetErrorMessageBuffer(
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
{
this->FunctorBase::SetErrorMessageBuffer(buffer);
this->Worklet.SetErrorMessageBuffer(buffer);
}
VTKM_SUPPRESS_EXEC_WARNINGS
template<typename T>
VTKM_EXEC
void operator()(T index) const
{
//Todo: rename this function to DoTaskSingular
detail::DoWorkletInvokeFunctor(this->Worklet,
this->Invocation,
this->Worklet.GetThreadIndices(index,
@ -64,10 +63,8 @@ public:
GlobalIndexOffset)
);
}
private:
WorkletType Worklet;
// This is held by by value so that when we transfer the invocation object
// over to CUDA it gets properly copied to the device. While we want to
// hold by reference to reduce the number of copies, it is not possible
@ -76,8 +73,9 @@ private:
const vtkm::Id GlobalIndexOffset;
};
}
}
} // vtkm::exec::internal
#endif //vtk_m_exec_internal_WorkletInvokeFunctor_h
#endif //vtk_m_exec_internal_TaskSingular_h

@ -28,8 +28,8 @@
#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h
#if !defined(vtk_m_exec_internal_TaskSingular_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h
#endif
#include <vtkm/internal/FunctionInterface.h>

@ -40,8 +40,8 @@ $# Ignore the following comment. It is meant for the generated file.
#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h
#if !defined(vtk_m_exec_internal_TaskSingular_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h
#endif
#include <vtkm/internal/FunctionInterface.h>

@ -22,6 +22,7 @@
set(unit_tests
UnitTestErrorMessageBuffer.cxx
UnitTestTaskSingular.cxx
UnitTestWorkletInvokeFunctor.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,309 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// 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/exec/internal/TaskSingular.h>
#include <vtkm/exec/arg/BasicArg.h>
#include <vtkm/exec/arg/ThreadIndicesBasic.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/internal/FunctionInterface.h>
#include <vtkm/internal/Invocation.h>
#include <vtkm/testing/Testing.h>
namespace {
struct TestExecObject
{
VTKM_EXEC_CONT
TestExecObject() : Value(NULL) { }
VTKM_EXEC_CONT
TestExecObject(vtkm::Id *value) : Value(value) { }
vtkm::Id *Value;
};
struct MyOutputToInputMapPortal
{
typedef vtkm::Id ValueType;
VTKM_EXEC_CONT
vtkm::Id Get(vtkm::Id index) const { return index; }
};
struct MyVisitArrayPortal
{
typedef vtkm::IdComponent ValueType;
vtkm::IdComponent Get(vtkm::Id) const { return 1; }
};
struct TestFetchTagInput { };
struct TestFetchTagOutput { };
// Missing TransportTag, but we are not testing that so we can leave it out.
struct TestControlSignatureTagInput
{
typedef TestFetchTagInput FetchTag;
};
struct TestControlSignatureTagOutput
{
typedef TestFetchTagOutput FetchTag;
};
} // anonymous namespace
namespace vtkm {
namespace exec {
namespace arg {
template<>
struct Fetch<
TestFetchTagInput,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesBasic,
TestExecObject>
{
typedef vtkm::Id ValueType;
VTKM_EXEC
ValueType Load(const vtkm::exec::arg::ThreadIndicesBasic &indices,
const TestExecObject &execObject) const {
return *execObject.Value + 10*indices.GetInputIndex();
}
VTKM_EXEC
void Store(const vtkm::exec::arg::ThreadIndicesBasic &,
const TestExecObject &,
ValueType) const {
// No-op
}
};
template<>
struct Fetch<
TestFetchTagOutput,
vtkm::exec::arg::AspectTagDefault,
vtkm::exec::arg::ThreadIndicesBasic,
TestExecObject>
{
typedef vtkm::Id ValueType;
VTKM_EXEC
ValueType Load(const vtkm::exec::arg::ThreadIndicesBasic &,
const TestExecObject &) const {
// No-op
return ValueType();
}
VTKM_EXEC
void Store(const vtkm::exec::arg::ThreadIndicesBasic &indices,
const TestExecObject &execObject,
ValueType value) const {
*execObject.Value = value + 20*indices.GetOutputIndex();
}
};
}
}
} // vtkm::exec::arg
namespace {
typedef void TestControlSignature(TestControlSignatureTagInput,
TestControlSignatureTagOutput);
typedef vtkm::internal::FunctionInterface<TestControlSignature>
TestControlInterface;
typedef void TestExecutionSignature1(vtkm::exec::arg::BasicArg<1>,
vtkm::exec::arg::BasicArg<2>);
typedef vtkm::internal::FunctionInterface<TestExecutionSignature1>
TestExecutionInterface1;
typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2(
vtkm::exec::arg::BasicArg<1>);
typedef vtkm::internal::FunctionInterface<TestExecutionSignature2>
TestExecutionInterface2;
typedef vtkm::internal::FunctionInterface<void(TestExecObject, TestExecObject)>
ExecutionParameterInterface;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface1,
1,
MyOutputToInputMapPortal,
MyVisitArrayPortal> InvocationType1;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface2,
1,
MyOutputToInputMapPortal,
MyVisitArrayPortal> InvocationType2;
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletProxy : vtkm::exec::FunctorBase
{
VTKM_EXEC
void operator()(vtkm::Id input, vtkm::Id &output) const
{
output = input + 100;
}
VTKM_EXEC
vtkm::Id operator()(vtkm::Id input) const
{
return input + 200;
}
template<typename T, typename OutToInArrayType, typename VisitArrayType,
typename InputDomainType, typename G>
VTKM_EXEC
vtkm::exec::arg::ThreadIndicesBasic
GetThreadIndices(const T& threadIndex,
const OutToInArrayType& outToIn,
const VisitArrayType& visit,
const InputDomainType &,
const G& globalThreadIndexOffset) const
{
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
outToIn.Get(threadIndex),
visit.Get(threadIndex),
globalThreadIndexOffset );
}
};
#define ERROR_MESSAGE "Expected worklet error."
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
{
VTKM_EXEC
void operator()(vtkm::Id, vtkm::Id) const
{
this->RaiseError(ERROR_MESSAGE);
}
template<typename T, typename OutToInArrayType, typename VisitArrayType,
typename InputDomainType, typename G>
VTKM_EXEC
vtkm::exec::arg::ThreadIndicesBasic
GetThreadIndices(const T& threadIndex,
const OutToInArrayType& outToIn,
const VisitArrayType& visit,
const InputDomainType &,
const G& globalThreadIndexOffset) const
{
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
outToIn.Get(threadIndex),
visit.Get(threadIndex),
globalThreadIndexOffset );
}
};
// Check behavior of InvocationToFetch helper class.
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,1>::type,
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,2>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType2,0>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
void TestNormalFunctorInvoke()
{
std::cout << "Testing normal worklet invoke." << std::endl;
vtkm::Id inputTestValue;
vtkm::Id outputTestValue;
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
std::cout << " Try void return." << std::endl;
inputTestValue = 5;
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
typedef vtkm::exec::internal::TaskSingular<TestWorkletProxy,InvocationType1> TaskSingular1;
TaskSingular1 taskInvokeWorklet1 =
TaskSingular1(TestWorkletProxy(), InvocationType1(execObjects));
taskInvokeWorklet1(1);
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
"Output value not set right.");
std::cout << " Try return value." << std::endl;
inputTestValue = 6;
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
typedef vtkm::exec::internal::TaskSingular<TestWorkletProxy,InvocationType2> TaskSingular2;
TaskSingular2 taskInvokeWorklet2 =
TaskSingular2(TestWorkletProxy(), InvocationType2(execObjects));
taskInvokeWorklet2(2);
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
"Output value not set right.");
}
void TestErrorFunctorInvoke()
{
std::cout << "Testing invoke with an error raised in the worklet." << std::endl;
vtkm::Id inputTestValue = 5;
vtkm::Id outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
typedef vtkm::exec::internal::TaskSingular<TestWorkletErrorProxy,InvocationType1> TaskSingular1;
TaskSingular1 taskInvokeWorklet1 =
TaskSingular1(TestWorkletErrorProxy(), InvocationType1(execObjects));
char message[1024];
message[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024);
taskInvokeWorklet1.SetErrorMessageBuffer(errorMessage);
taskInvokeWorklet1(1);
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly.");
VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE),
"Got wrong error message.");
}
void TestTaskSingular()
{
TestNormalFunctorInvoke();
TestErrorFunctorInvoke();
}
} // anonymous namespace
int UnitTestTaskSingular(int, char *[])
{
return vtkm::testing::Testing::Run(TestTaskSingular);
}

@ -18,8 +18,9 @@
// this software.
//============================================================================
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <vtkm/exec/internal/TaskSingular.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/exec/arg/BasicArg.h>
#include <vtkm/exec/arg/ThreadIndicesBasic.h>
@ -143,25 +144,6 @@ typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2(
typedef vtkm::internal::FunctionInterface<TestExecutionSignature2>
TestExecutionInterface2;
typedef vtkm::internal::FunctionInterface<void(TestExecObject, TestExecObject)>
ExecutionParameterInterface;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface1,
1,
MyOutputToInputMapPortal,
MyVisitArrayPortal> InvocationType1;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface2,
1,
MyOutputToInputMapPortal,
MyVisitArrayPortal> InvocationType2;
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletProxy : vtkm::exec::FunctorBase
{
@ -177,7 +159,7 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
return input + 200;
}
template<typename T, typename OutToInArrayType, typename VisitArrayType,
template<typename T, typename OutToInArrayType, typename VisitArrayType,
typename InputDomainType, typename G>
VTKM_EXEC
vtkm::exec::arg::ThreadIndicesBasic
@ -194,48 +176,6 @@ struct TestWorkletProxy : vtkm::exec::FunctorBase
}
};
#define ERROR_MESSAGE "Expected worklet error."
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
{
VTKM_EXEC
void operator()(vtkm::Id, vtkm::Id) const
{
this->RaiseError(ERROR_MESSAGE);
}
template<typename T, typename OutToInArrayType, typename VisitArrayType,
typename InputDomainType, typename G>
VTKM_EXEC
vtkm::exec::arg::ThreadIndicesBasic
GetThreadIndices(const T& threadIndex,
const OutToInArrayType& outToIn,
const VisitArrayType& visit,
const InputDomainType &,
const G& globalThreadIndexOffset) const
{
return vtkm::exec::arg::ThreadIndicesBasic(threadIndex,
outToIn.Get(threadIndex),
visit.Get(threadIndex),
globalThreadIndexOffset );
}
};
// Check behavior of InvocationToFetch helper class.
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,1>::type,
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType1,2>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
VTKM_STATIC_ASSERT(( std::is_same<
vtkm::exec::internal::detail::InvocationToFetch<vtkm::exec::arg::ThreadIndicesBasic,InvocationType2,0>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,vtkm::exec::arg::ThreadIndicesBasic,TestExecObject> >::type::value ));
template<typename Invocation>
void CallDoWorkletInvokeFunctor(const Invocation &invocation, vtkm::Id index)
{
@ -287,68 +227,10 @@ void TestDoWorkletInvoke()
"Output value not set right.");
}
void TestNormalFunctorInvoke()
{
std::cout << "Testing normal worklet invoke." << std::endl;
vtkm::Id inputTestValue;
vtkm::Id outputTestValue;
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
std::cout << " Try void return." << std::endl;
inputTestValue = 5;
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType1> WorkletInvokeFunctor1;
WorkletInvokeFunctor1 workletInvokeFunctor1 =
WorkletInvokeFunctor1(TestWorkletProxy(), InvocationType1(execObjects));
workletInvokeFunctor1(1);
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
"Output value not set right.");
std::cout << " Try return value." << std::endl;
inputTestValue = 6;
outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType2> WorkletInvokeFunctor2;
WorkletInvokeFunctor2 workletInvokeFunctor2 =
WorkletInvokeFunctor2(TestWorkletProxy(), InvocationType2(execObjects));
workletInvokeFunctor2(2);
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
"Output value not set right.");
}
void TestErrorFunctorInvoke()
{
std::cout << "Testing invoke with an error raised in the worklet." << std::endl;
vtkm::Id inputTestValue = 5;
vtkm::Id outputTestValue = static_cast<vtkm::Id>(0xDEADDEAD);
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletErrorProxy,InvocationType1> WorkletInvokeFunctor1;
WorkletInvokeFunctor1 workletInvokeFunctor1 =
WorkletInvokeFunctor1(TestWorkletErrorProxy(), InvocationType1(execObjects));
char message[1024];
message[0] = '\0';
vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024);
workletInvokeFunctor1.SetErrorMessageBuffer(errorMessage);
workletInvokeFunctor1(1);
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly.");
VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE),
"Got wrong error message.");
}
void TestWorkletInvokeFunctor()
{
TestDoWorkletInvoke();
TestNormalFunctorInvoke();
TestErrorFunctorInvoke();
}
} // anonymous namespace

@ -41,7 +41,7 @@ struct DispatcherStreamingMapFieldTransformFunctor
VTKM_CONT
DispatcherStreamingMapFieldTransformFunctor(
vtkm::Id blockIndex, vtkm::Id blockSize, vtkm::Id curBlockSize, vtkm::Id fullSize)
: BlockIndex(blockIndex), BlockSize(blockSize),
: BlockIndex(blockIndex), BlockSize(blockSize),
CurBlockSize(curBlockSize), FullSize(fullSize) { }
template<typename ParameterType, bool IsArrayHandle>
@ -73,10 +73,10 @@ struct DispatcherStreamingMapFieldTransformFunctor
{
VTKM_CONT
vtkm::cont::ArrayHandleStreaming<ArrayHandleType>
operator()(const ArrayHandleType &array, vtkm::Id blockIndex,
operator()(const ArrayHandleType &array, vtkm::Id blockIndex,
vtkm::Id blockSize, vtkm::Id curBlockSize, vtkm::Id fullSize) const
{
vtkm::cont::ArrayHandleStreaming<ArrayHandleType> result =
vtkm::cont::ArrayHandleStreaming<ArrayHandleType> result =
vtkm::cont::ArrayHandleStreaming<ArrayHandleType>(
array, blockIndex, blockSize, curBlockSize);
if (blockIndex == 0) result.AllocateFullArray(fullSize);
@ -100,7 +100,7 @@ struct DispatcherStreamingMapFieldTransformFunctor
operator()(const ParameterType &invokeData,
vtkm::internal::IndexTag<Index>) const
{
return TransformImpl<ParameterType,
return TransformImpl<ParameterType,
vtkm::cont::internal::ArrayHandleCheck<ParameterType>::type::value>()
(invokeData, this->BlockIndex, this->BlockSize, this->CurBlockSize, this->FullSize);
}
@ -115,7 +115,7 @@ struct DispatcherStreamingMapFieldTransferFunctor
template<typename ParameterType, vtkm::IdComponent Index>
struct ReturnType {
typedef ParameterType type;
typedef ParameterType type;
};
template<typename ParameterType, bool IsArrayHandle>
@ -178,7 +178,7 @@ public:
: Superclass(worklet), NumberOfBlocks(1) { }
VTKM_CONT
void SetNumberOfBlocks(vtkm::Id numberOfBlocks)
void SetNumberOfBlocks(vtkm::Id numberOfBlocks)
{
NumberOfBlocks = numberOfBlocks;
}
@ -216,7 +216,7 @@ public:
vtkm::Id fullSize = inputDomain.GetNumberOfValues();
vtkm::Id blockSize = fullSize / NumberOfBlocks;
if (fullSize % NumberOfBlocks != 0) blockSize += 1;
typedef detail::DispatcherStreamingMapFieldTransformFunctor<
typename Invocation::ControlInterface, Device> TransformFunctorType;
typedef detail::DispatcherStreamingMapFieldTransferFunctor<
@ -227,7 +227,7 @@ public:
{
// Account for domain sizes not evenly divisable by the number of blocks
vtkm::Id numberOfInstances = blockSize;
if (block == NumberOfBlocks-1)
if (block == NumberOfBlocks-1)
numberOfInstances = fullSize - blockSize*block;
vtkm::Id globalIndexOffset = blockSize*block;
@ -237,7 +237,7 @@ public:
ReportedType newParams = invocation.Parameters.StaticTransformCont(
TransformFunctorType(block, blockSize, numberOfInstances, fullSize));
typedef typename Invocation::template
typedef typename Invocation::template
ChangeParametersType<ReportedType>::type ChangedType;
ChangedType changedParams = invocation.ChangeParameters(newParams);
@ -302,17 +302,15 @@ private:
RangeType globalIndexOffset,
DeviceAdapter) const
{
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
// The WorkletInvokeFunctor class handles the magic of fetching values
// for each instance and calling the worklet's function. So just create
// a WorkletInvokeFunctor and schedule it with the device adapter.
typedef vtkm::exec::internal::WorkletInvokeFunctor<WorkletType,Invocation>
WorkletInvokeFunctorType;
WorkletInvokeFunctorType workletFunctor =
WorkletInvokeFunctorType(this->Worklet, invocation, globalIndexOffset);
using TaskType = vtkm::exec::internal::TaskSingular<WorkletType,Invocation>;
TaskType task = TaskType(this->Worklet, invocation, globalIndexOffset);
typedef vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter> Algorithm;
Algorithm::Schedule(workletFunctor, range);
Algorithm::Schedule(task, range);
}

@ -34,7 +34,7 @@
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/exec/arg/ExecutionSignatureTagBase.h>
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <vtkm/exec/internal/TaskSingular.h>
#include <vtkm/internal/IntegerSequence.h>
#include <vtkm/internal/brigand.hpp>
@ -531,10 +531,10 @@ private:
RangeType range,
DeviceAdapter) const
{
// The WorkletInvokeFunctor class handles the magic of fetching values
// The TaskSingular class handles the magic of fetching values
// for each instance and calling the worklet's function. So just create
// a WorkletInvokeFunctor and schedule it with the device adapter.
typedef vtkm::exec::internal::WorkletInvokeFunctor<WorkletType,Invocation>
// a TaskSingular and schedule it with the device adapter.
typedef vtkm::exec::internal::TaskSingular<WorkletType,Invocation>
WorkletInvokeFunctorType;
WorkletInvokeFunctorType workletFunctor =
WorkletInvokeFunctorType(this->Worklet, invocation);