mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Add basic dispatcher functionality.
These changes support the implementation of DispatcherBase. This class provides the basic functionality for calling an Invoke method in the control environment, transferring data to the execution environment, scheduling threads in the execution environment, pulling data for each calling of the worklet method, and actually calling the worklet.
This commit is contained in:
parent
b78688f4f4
commit
53a454fe77
@ -83,7 +83,9 @@ struct FetchArrayDirectInTests
|
||||
|
||||
this->TryInvocation(vtkm::internal::make_Invocation<1>(
|
||||
BaseFunctionInterface().Replace<ParamIndex>(
|
||||
TestPortal<T>())));
|
||||
TestPortal<T>()),
|
||||
NullParam(),
|
||||
NullParam()));
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -94,7 +94,9 @@ struct FetchArrayDirectOutTests
|
||||
|
||||
this->TryInvocation(vtkm::internal::make_Invocation<1>(
|
||||
BaseFunctionInterface().Replace<ParamIndex>(
|
||||
TestPortal<T>())));
|
||||
TestPortal<T>()),
|
||||
NullParam(),
|
||||
NullParam()));
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -78,7 +78,9 @@ void TryParamIndex()
|
||||
|
||||
TryInvocation<ParamIndex>(vtkm::internal::make_Invocation<1>(
|
||||
BaseFunctionInterface().Replace<ParamIndex>(
|
||||
TestExecutionObject(EXPECTED_NUMBER))));
|
||||
TestExecutionObject(EXPECTED_NUMBER)),
|
||||
NullParam(),
|
||||
NullParam()));
|
||||
}
|
||||
|
||||
void TestExecObjectFetch()
|
||||
|
@ -63,7 +63,9 @@ void TestWorkIndexFetch()
|
||||
void(NullParam,NullParam,NullParam,NullParam,NullParam)>
|
||||
BaseFunctionInterface;
|
||||
|
||||
TryInvocation(vtkm::internal::make_Invocation<1>( BaseFunctionInterface()));
|
||||
TryInvocation(vtkm::internal::make_Invocation<1>(BaseFunctionInterface(),
|
||||
NullParam(),
|
||||
NullParam()));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -20,8 +20,12 @@
|
||||
|
||||
set(headers
|
||||
ErrorMessageBuffer.h
|
||||
WorkletInvokeFunctor.h
|
||||
WorkletInvokeFunctorDetail.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
||||
vtkm_pyexpander_generated_file(WorkletInvokeFunctorDetail.h)
|
||||
|
||||
add_subdirectory(testing)
|
||||
|
67
vtkm/exec/internal/WorkletInvokeFunctor.h
Normal file
67
vtkm/exec/internal/WorkletInvokeFunctor.h
Normal file
@ -0,0 +1,67 @@
|
||||
//============================================================================
|
||||
// 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_internal_WorkletInvokeFunctor_h
|
||||
#define vtk_m_exec_internal_WorkletInvokeFunctor_h
|
||||
|
||||
#include <vtkm/internal/Invocation.h>
|
||||
|
||||
#include <vtkm/exec/FunctorBase.h>
|
||||
|
||||
#include <vtkm/exec/arg/Fetch.h>
|
||||
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctorDetail.h>
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace internal {
|
||||
|
||||
template<typename WorkletType, typename InvocationType>
|
||||
class WorkletInvokeFunctor : public vtkm::exec::FunctorBase
|
||||
{
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
WorkletInvokeFunctor(const WorkletType &worklet,
|
||||
const InvocationType &invocation)
|
||||
: Worklet(worklet), Invocation(invocation) { }
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void SetErrorMessageBuffer(
|
||||
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
|
||||
{
|
||||
this->FunctorBase::SetErrorMessageBuffer(buffer);
|
||||
this->Worklet.SetErrorMessageBuffer(buffer);
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id index) const
|
||||
{
|
||||
detail::DoWorkletInvokeFunctor(this->Worklet, this->Invocation, index);
|
||||
}
|
||||
|
||||
private:
|
||||
WorkletType Worklet;
|
||||
InvocationType Invocation;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // vtkm::exec::internal
|
||||
|
||||
#endif //vtk_m_exec_internal_WorkletInvokeFunctor_h
|
1256
vtkm/exec/internal/WorkletInvokeFunctorDetail.h
Normal file
1256
vtkm/exec/internal/WorkletInvokeFunctorDetail.h
Normal file
File diff suppressed because it is too large
Load Diff
219
vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in
Normal file
219
vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in
Normal file
@ -0,0 +1,219 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
$# This file uses the pyexpander macro processing utility to build the
|
||||
$# FunctionInterface facilities that use a variable number of arguments.
|
||||
$# Information, documentation, and downloads for pyexpander can be found at:
|
||||
$#
|
||||
$# http://pyexpander.sourceforge.net/
|
||||
$#
|
||||
$# To build the source code, execute the following (after installing
|
||||
$# pyexpander, of course):
|
||||
$#
|
||||
$# expander.py WorkletInvokeFunctorDetail.h.in > WorkletInvokeFunctorDetail.h
|
||||
$#
|
||||
$# Ignore the following comment. It is meant for the generated file.
|
||||
// **** DO NOT EDIT THIS FILE!!! ****
|
||||
// This file is automatically generated by WorkletInvokeFunctorDetail.h.in
|
||||
|
||||
// Technically speaking, we can implement this functionality with some clever
|
||||
// use of FunctionInterface rather than using pyexpander to make variadic
|
||||
// code. However, this code is probably more friendly to compilers. I expect
|
||||
// it to compiler faster and optimize better.
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
#include <vtkm/internal/Invocation.h>
|
||||
|
||||
#include <vtkm/exec/arg/Fetch.h>
|
||||
|
||||
$# This needs to match the max_parameters in FunctionInterfaceDetailPre.h.in
|
||||
$py(max_parameters=10)\
|
||||
#if VTKM_MAX_FUNCTION_PARAMETERS != $(max_parameters)
|
||||
#error Mismatch of maximum parameters between FunctionInterfaceDatailPre.h.in and WorkletInvokeFunctorDetail.h.in
|
||||
#endif
|
||||
|
||||
$# Python commands used in template expansion.
|
||||
$py(
|
||||
def comma_if(flag):
|
||||
if flag:
|
||||
return ','
|
||||
else:
|
||||
return '';
|
||||
|
||||
def ptype(num, name=''):
|
||||
if num == 0:
|
||||
return '%sR' % name
|
||||
else:
|
||||
return '%sP%d' % (name, num)
|
||||
|
||||
def pname(num, name=''):
|
||||
if num == 0:
|
||||
return '%sr' % name
|
||||
else:
|
||||
return '%sp%d' % (name, num)
|
||||
|
||||
def template_params(num_params, start=0, name=''):
|
||||
if num_params < start:
|
||||
return ''
|
||||
result = 'typename %s' % ptype(start, name)
|
||||
for param in xrange(start+1, num_params+1):
|
||||
result += ',\n typename %s' % ptype(param, name)
|
||||
return result
|
||||
|
||||
def signature(num_params, return_type=ptype(0), name=''):
|
||||
result = '%s(' % return_type
|
||||
if num_params > 0:
|
||||
result += ptype(1, name)
|
||||
for param in xrange(2, num_params+1):
|
||||
result += ',%s' % ptype(param, name)
|
||||
result += ')'
|
||||
return result
|
||||
|
||||
def arg_list(num_params, name='', start=1):
|
||||
if num_params < start:
|
||||
return ''
|
||||
result = pname(start, name)
|
||||
for param in xrange(start+1, num_params+1):
|
||||
result += ',%s' % pname(param, name)
|
||||
return result
|
||||
)\
|
||||
$#
|
||||
$extend(comma_if, ptype, pname, template_params, signature, arg_list)\
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace internal {
|
||||
namespace detail {
|
||||
|
||||
/// A helper class that takes an \c Invocation object and an index to a
|
||||
/// parameter in the ExecutionSignature and finds the \c Fetch type valid for
|
||||
/// that parameter.
|
||||
template<typename Invocation, vtkm::IdComponent ExecutionParameterIndex>
|
||||
struct InvocationToFetch
|
||||
{
|
||||
private:
|
||||
typedef typename Invocation::ExecutionInterface::
|
||||
template ParameterType<ExecutionParameterIndex>::type
|
||||
ExecutionSignatureTag;
|
||||
|
||||
// Expected fields from ExecutionSignatureTag. If these do not exist in
|
||||
// ExecutionSignatureTag, then something that is not really an execution
|
||||
// signature tag was used in an ExecutionSignature.
|
||||
static const vtkm::IdComponent ControlParameterIndex =
|
||||
ExecutionSignatureTag::INDEX;
|
||||
typedef typename ExecutionSignatureTag::AspectTag AspectTag;
|
||||
|
||||
// Find the fetch tag from the control signature tag pointed to by
|
||||
// ParameterIndex.
|
||||
typedef typename Invocation::ControlInterface ControlInterface;
|
||||
typedef typename ControlInterface::
|
||||
template ParameterType<ControlParameterIndex>::type ControlSignatureTag;
|
||||
typedef typename ControlSignatureTag::FetchTag FetchTag;
|
||||
|
||||
public:
|
||||
typedef vtkm::exec::arg::Fetch<
|
||||
FetchTag,AspectTag,Invocation,ControlParameterIndex> type;
|
||||
};
|
||||
|
||||
$for(num_params in range(1, max_parameters+1))\
|
||||
template<typename WorkletType,
|
||||
typename ParameterInterface,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
$template_params(num_params)>
|
||||
void DoWorkletInvokeFunctor(
|
||||
const WorkletType &worklet,
|
||||
const vtkm::internal::Invocation<
|
||||
ParameterInterface,
|
||||
ControlInterface,
|
||||
vtkm::internal::FunctionInterface<$signature(num_params)>,
|
||||
InputDomainIndex> &invocation,
|
||||
vtkm::Id index)
|
||||
{
|
||||
typedef vtkm::internal::Invocation<
|
||||
ParameterInterface,
|
||||
ControlInterface,
|
||||
vtkm::internal::FunctionInterface<$signature(num_params)>,
|
||||
InputDomainIndex> Invocation;
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
|
||||
typedef typename InvocationToFetch<Invocation,$(param_index)>::type FetchType$(param_index);
|
||||
FetchType$(param_index) fetch$(param_index);
|
||||
typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation);
|
||||
$endfor\
|
||||
|
||||
typedef typename InvocationToFetch<Invocation,0>::type ReturnFetchType;
|
||||
ReturnFetchType returnFetch;
|
||||
typename ReturnFetchType::ValueType $pname(0) = worklet($arg_list(num_params));
|
||||
|
||||
returnFetch.Store(index, invocation, $pname(0));
|
||||
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
fetch$(param_index).Store(index, invocation, $pname(param_index));
|
||||
$endfor\
|
||||
}
|
||||
|
||||
template<typename WorkletType,
|
||||
typename ParameterInterface,
|
||||
typename ControlInterface,
|
||||
vtkm::IdComponent InputDomainIndex,
|
||||
$template_params(num_params, start=1)>
|
||||
void DoWorkletInvokeFunctor(
|
||||
const WorkletType &worklet,
|
||||
const vtkm::internal::Invocation<
|
||||
ParameterInterface,
|
||||
ControlInterface,
|
||||
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
|
||||
InputDomainIndex> &invocation,
|
||||
vtkm::Id index)
|
||||
{
|
||||
typedef vtkm::internal::Invocation<
|
||||
ParameterInterface,
|
||||
ControlInterface,
|
||||
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
|
||||
InputDomainIndex> Invocation;
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
|
||||
typedef typename InvocationToFetch<Invocation,$(param_index)>::type FetchType$(param_index);
|
||||
FetchType$(param_index) fetch$(param_index);
|
||||
typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation);
|
||||
$endfor\
|
||||
|
||||
worklet($arg_list(num_params));
|
||||
|
||||
$for(param_index in range(1, num_params+1))\
|
||||
fetch$(param_index).Store(index, invocation, $pname(param_index));
|
||||
$endfor\
|
||||
}
|
||||
|
||||
$endfor\
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::exec::internal::detail
|
||||
|
||||
#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
|
@ -22,5 +22,6 @@
|
||||
|
||||
set(unit_tests
|
||||
UnitTestErrorMessageBuffer.cxx
|
||||
UnitTestWorkletInvokeFunctor.cxx
|
||||
)
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
||||
|
284
vtkm/exec/internal/testing/UnitTestWorkletInvokeFunctor.cxx
Normal file
284
vtkm/exec/internal/testing/UnitTestWorkletInvokeFunctor.cxx
Normal file
@ -0,0 +1,284 @@
|
||||
//============================================================================
|
||||
// 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/WorkletInvokeFunctor.h>
|
||||
|
||||
#include <vtkm/exec/arg/BasicArg.h>
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
|
||||
#include <vtkm/testing/Testing.h>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
struct TestExecObject
|
||||
{
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
TestExecObject() : Value(NULL) { }
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
TestExecObject(vtkm::Id *value) : Value(value) { }
|
||||
|
||||
vtkm::Id *Value;
|
||||
};
|
||||
|
||||
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<typename Invocation, vtkm::IdComponent ParameterIndex>
|
||||
struct Fetch<TestFetchTagInput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
ValueType Load(vtkm::Id index, const Invocation &invocation) const {
|
||||
return *invocation.Parameters.
|
||||
template GetParameter<ParameterIndex>().Value + 10*index;
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void Store(vtkm::Id, const Invocation &, ValueType) const {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Invocation, vtkm::IdComponent ParameterIndex>
|
||||
struct Fetch<TestFetchTagOutput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
ValueType Load(vtkm::Id, const Invocation &) const {
|
||||
// No-op
|
||||
return ValueType();
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void Store(vtkm::Id index,
|
||||
const Invocation &invocation,
|
||||
ValueType value) const {
|
||||
*invocation.Parameters.template GetParameter<ParameterIndex>().Value =
|
||||
value + 20*index;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // 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> InvocationType1;
|
||||
|
||||
typedef vtkm::internal::Invocation<
|
||||
ExecutionParameterInterface,
|
||||
TestControlInterface,
|
||||
TestExecutionInterface2,
|
||||
1> InvocationType2;
|
||||
|
||||
// Not a full worklet, but provides operators that we expect in a worklet.
|
||||
struct TestWorkletProxy : vtkm::exec::FunctorBase
|
||||
{
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id input, vtkm::Id &output) const
|
||||
{
|
||||
output = input + 100;
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
vtkm::Id operator()(vtkm::Id input) const
|
||||
{
|
||||
return input + 200;
|
||||
}
|
||||
};
|
||||
|
||||
#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_EXPORT
|
||||
void operator()(vtkm::Id, vtkm::Id) const
|
||||
{
|
||||
this->RaiseError(ERROR_MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// Check behavior of InvocationToFetch helper class.
|
||||
|
||||
BOOST_MPL_ASSERT(( boost::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<InvocationType1,1>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,InvocationType1,1> > ));
|
||||
|
||||
BOOST_MPL_ASSERT(( boost::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<InvocationType1,2>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,InvocationType1,2> > ));
|
||||
|
||||
BOOST_MPL_ASSERT(( boost::is_same<
|
||||
vtkm::exec::internal::detail::InvocationToFetch<InvocationType2,0>::type,
|
||||
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,InvocationType2,2> > ));
|
||||
|
||||
void TestDoWorkletInvoke()
|
||||
{
|
||||
std::cout << "Testing internal 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 = 0xDEADDEAD;
|
||||
vtkm::exec::internal::detail::DoWorkletInvokeFunctor(
|
||||
TestWorkletProxy(),
|
||||
vtkm::internal::make_Invocation<1>(execObjects,
|
||||
TestControlInterface(),
|
||||
TestExecutionInterface1()),
|
||||
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 = 0xDEADDEAD;
|
||||
vtkm::exec::internal::detail::DoWorkletInvokeFunctor(
|
||||
TestWorkletProxy(),
|
||||
vtkm::internal::make_Invocation<1>(execObjects,
|
||||
TestControlInterface(),
|
||||
TestExecutionInterface2()),
|
||||
2);
|
||||
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
|
||||
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
|
||||
"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 = 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 = 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 = 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];
|
||||
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
|
||||
|
||||
int UnitTestWorkletInvokeFunctor(int, char *[])
|
||||
{
|
||||
return vtkm::testing::Testing::Run(TestWorkletInvokeFunctor);
|
||||
}
|
@ -625,7 +625,7 @@ public:
|
||||
template<typename TransformFunctor, typename FinishFunctor>
|
||||
VTKM_CONT_EXPORT
|
||||
void DynamicTransformCont(const TransformFunctor &transform,
|
||||
const FinishFunctor &finish) {
|
||||
const FinishFunctor &finish) const {
|
||||
typedef detail::FunctionInterfaceDynamicTransformContContinue<
|
||||
FunctionSignature,
|
||||
ResultType(),
|
||||
@ -637,7 +637,7 @@ public:
|
||||
ContinueFunctorType(*this, emptyInterface, transform, finish);
|
||||
|
||||
continueFunctor.DoNextTransform(emptyInterface);
|
||||
this->Result = emptyInterface.GetReturnValueSafe();
|
||||
// this->Result = emptyInterface.GetReturnValueSafe();
|
||||
}
|
||||
|
||||
/// \brief Applies a function to all the parameters.
|
||||
@ -682,7 +682,7 @@ class FunctionInterfaceDynamicTransformContContinue
|
||||
{
|
||||
public:
|
||||
FunctionInterfaceDynamicTransformContContinue(
|
||||
vtkm::internal::FunctionInterface<OriginalFunction> &originalInterface,
|
||||
const vtkm::internal::FunctionInterface<OriginalFunction> &originalInterface,
|
||||
vtkm::internal::FunctionInterface<NewFunction> &newInterface,
|
||||
const TransformFunctor &transform,
|
||||
const FinishFunctor &finish)
|
||||
@ -740,7 +740,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::internal::FunctionInterface<OriginalFunction> &OriginalInterface;
|
||||
const vtkm::internal::FunctionInterface<OriginalFunction> &OriginalInterface;
|
||||
vtkm::internal::FunctionInterface<NewFunction> &NewInterface;
|
||||
const TransformFunctor &Transform;
|
||||
const FinishFunctor &Finish;
|
||||
|
@ -32,16 +32,34 @@ namespace internal {
|
||||
/// worklet. \c Invocation is a class that manages all these types.
|
||||
///
|
||||
template<typename _ParameterInterface,
|
||||
typename _ControlInterface,
|
||||
typename _ExecutionInterface,
|
||||
vtkm::IdComponent _InputDomainIndex>
|
||||
struct Invocation
|
||||
{
|
||||
/// \brief The types of the parameters
|
||||
///
|
||||
/// \c ParameterInterface is (expected to be) a FunctionInterface class that
|
||||
/// lists the types of the parameters for the invocation.
|
||||
/// \c ParameterInterface is (expected to be) a \c FunctionInterface class
|
||||
/// that lists the types of the parameters for the invocation.
|
||||
///
|
||||
typedef _ParameterInterface ParameterInterface;
|
||||
|
||||
/// \brief The tags of the \c ControlSignature.
|
||||
///
|
||||
/// \c ControlInterface is (expected to be) a \c FunctionInterface class that
|
||||
/// represents the \c ControlSignature of a worklet (although dispatchers
|
||||
/// might modify the control signature to provide auxiliary information).
|
||||
///
|
||||
typedef _ControlInterface ControlInterface;
|
||||
|
||||
/// \brief The tags of the \c ExecutionSignature.
|
||||
///
|
||||
/// \c ExecutionInterface is (expected to be) a \c FunctionInterface class that
|
||||
/// represents the \c ExecutionSignature of a worklet (although dispatchers
|
||||
/// might modify the execution signature to provide auxiliary information).
|
||||
///
|
||||
typedef _ExecutionInterface ExecutionInterface;
|
||||
|
||||
/// \brief The index of the input domain.
|
||||
///
|
||||
/// When a worklet is invoked, the pool of working threads is based of some
|
||||
@ -58,11 +76,14 @@ struct Invocation
|
||||
///
|
||||
template<typename NewParameterInterface>
|
||||
struct ChangeParametersType {
|
||||
typedef Invocation<NewParameterInterface,InputDomainIndex> type;
|
||||
typedef Invocation<NewParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex> type;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
/// \c Parameters type is changed to the type given.
|
||||
/// \c Parameters are replaced with those provided.
|
||||
///
|
||||
template<typename NewParameterInterface>
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
@ -72,12 +93,57 @@ struct Invocation
|
||||
newParameters);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
/// with the \c ControlInterface replaced.
|
||||
///
|
||||
template<typename NewControlInterface>
|
||||
struct ChangeControlInterfaceType {
|
||||
typedef Invocation<ParameterInterface,
|
||||
NewControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex> type;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
/// \c ControlInterface type is changed to the type given.
|
||||
///
|
||||
template<typename NewControlInterface>
|
||||
typename ChangeControlInterfaceType<NewControlInterface>::type
|
||||
ChangeControlInterface(NewControlInterface) const {
|
||||
return typename ChangeControlInterfaceType<NewControlInterface>::type(
|
||||
this->Parameters);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
/// with the \c ExecutionInterface replaced.
|
||||
///
|
||||
template<typename NewExecutionInterface>
|
||||
struct ChangeExecutionInterfaceType {
|
||||
typedef Invocation<ParameterInterface,
|
||||
NewExecutionInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex> type;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
/// \c ExecutionInterface type is changed to the type given.
|
||||
///
|
||||
template<typename NewExecutionInterface>
|
||||
typename ChangeExecutionInterfaceType<NewExecutionInterface>::type
|
||||
ChangeExecutionInterface(NewExecutionInterface) const {
|
||||
return typename ChangeExecutionInterfaceType<NewExecutionInterface>::type(
|
||||
this->Parameters);
|
||||
}
|
||||
|
||||
/// Defines a new \c Invocation type that is the same as this type except
|
||||
/// with the \c InputDomainIndex replaced.
|
||||
///
|
||||
template<vtkm::IdComponent NewInputDomainIndex>
|
||||
struct ChangeInputDomainIndexType {
|
||||
typedef Invocation<ParameterInterface,NewInputDomainIndex> type;
|
||||
typedef Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
NewInputDomainIndex> type;
|
||||
};
|
||||
|
||||
/// Returns a new \c Invocation that is the same as this one except that the
|
||||
@ -100,12 +166,21 @@ struct Invocation
|
||||
/// Convenience function for creating an Invocation object.
|
||||
///
|
||||
template<vtkm::IdComponent InputDomainIndex,
|
||||
typename ControlInterface,
|
||||
typename ExecutionInterface,
|
||||
typename ParameterInterface>
|
||||
VTKM_CONT_EXPORT
|
||||
vtkm::internal::Invocation<ParameterInterface, InputDomainIndex>
|
||||
make_Invocation(const ParameterInterface ¶ms)
|
||||
vtkm::internal::Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex>
|
||||
make_Invocation(const ParameterInterface ¶ms,
|
||||
ControlInterface = ControlInterface(),
|
||||
ExecutionInterface = ExecutionInterface())
|
||||
{
|
||||
return vtkm::internal::Invocation<ParameterInterface,
|
||||
ControlInterface,
|
||||
ExecutionInterface,
|
||||
InputDomainIndex>(params);
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,12 @@
|
||||
##============================================================================
|
||||
|
||||
set(headers
|
||||
DispatcherBase.h
|
||||
WorkletBase.h
|
||||
)
|
||||
|
||||
vtkm_declare_headers(${headers})
|
||||
|
||||
#add_subdirectory(testing)
|
||||
vtkm_pyexpander_generated_file(DispatcherBaseDetailInvoke.h)
|
||||
|
||||
add_subdirectory(testing)
|
||||
|
230
vtkm/worklet/internal/DispatcherBase.h
Normal file
230
vtkm/worklet/internal/DispatcherBase.h
Normal file
@ -0,0 +1,230 @@
|
||||
//============================================================================
|
||||
// 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_worklet_internal_DispatcherBase_h
|
||||
#define vtk_m_worklet_internal_DispatcherBase_h
|
||||
|
||||
#include <vtkm/internal/FunctionInterface.h>
|
||||
#include <vtkm/internal/Invocation.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapter.h>
|
||||
|
||||
#include <vtkm/cont/arg/Transport.h>
|
||||
|
||||
#include <vtkm/cont/internal/DynamicTransform.h>
|
||||
|
||||
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
|
||||
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
namespace vtkm {
|
||||
namespace worklet {
|
||||
namespace internal {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename DispatcherBaseType>
|
||||
struct DispatcherBaseDynamicTransformHelper
|
||||
{
|
||||
const DispatcherBaseType *Dispatcher;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
DispatcherBaseDynamicTransformHelper(const DispatcherBaseType *dispatcher)
|
||||
: Dispatcher(dispatcher) { }
|
||||
|
||||
template<typename FunctionInterface>
|
||||
VTKM_CONT_EXPORT
|
||||
void operator()(const FunctionInterface ¶meters) const {
|
||||
this->Dispatcher->DynamicTransformInvoke(parameters);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Device>
|
||||
struct DispatcherBaseTransportFunctor
|
||||
{
|
||||
vtkm::Id NumInstances;
|
||||
|
||||
DispatcherBaseTransportFunctor(vtkm::Id numInstances)
|
||||
: NumInstances(numInstances) { }
|
||||
|
||||
template<typename T>
|
||||
struct InvokeTypes {
|
||||
typedef typename T::FirstType::TransportTag TransportTag;
|
||||
typedef typename T::SecondType ControlParameter;
|
||||
typedef vtkm::cont::arg::Transport<TransportTag,ControlParameter,Device>
|
||||
TransportType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ReturnType {
|
||||
typedef typename InvokeTypes<T>::TransportType::ExecObjectType type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
VTKM_CONT_EXPORT
|
||||
typename ReturnType<T>::type
|
||||
operator()(const T &invokeData) const {
|
||||
typename InvokeTypes<T>::TransportType transport;
|
||||
return transport(invokeData.second, this->NumInstances);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Base class for all dispatcher classes. Every worklet type should have its
|
||||
/// own dispatcher.
|
||||
///
|
||||
template<typename DerivedClass,
|
||||
typename WorkletType,
|
||||
typename BaseWorkletType,
|
||||
typename Device>
|
||||
class DispatcherBase
|
||||
{
|
||||
private:
|
||||
typedef DispatcherBase<DerivedClass,WorkletType,BaseWorkletType,Device> MyType;
|
||||
|
||||
friend struct detail::DispatcherBaseDynamicTransformHelper<MyType>;
|
||||
|
||||
protected:
|
||||
typedef vtkm::internal::FunctionInterface<
|
||||
typename WorkletType::ControlSignature> ControlInterface;
|
||||
typedef vtkm::internal::FunctionInterface<
|
||||
typename WorkletType::ExecutionSignature> ExecutionInterface;
|
||||
|
||||
static const vtkm::IdComponent NUM_INVOKE_PARAMS = ControlInterface::ARITY;
|
||||
|
||||
template<typename Signature>
|
||||
VTKM_CONT_EXPORT
|
||||
void StartInvoke(
|
||||
const vtkm::internal::FunctionInterface<Signature> ¶meters) const
|
||||
{
|
||||
typedef vtkm::internal::FunctionInterface<Signature> ParameterInterface;
|
||||
BOOST_STATIC_ASSERT_MSG(ParameterInterface::ARITY == NUM_INVOKE_PARAMS,
|
||||
"Dispatcher Invoke called with wrong number of arguments.");
|
||||
|
||||
BOOST_MPL_ASSERT(( boost::is_base_of<BaseWorkletType,WorkletType> ));
|
||||
|
||||
parameters.DynamicTransformCont(
|
||||
vtkm::cont::internal::DynamicTransform(),
|
||||
detail::DispatcherBaseDynamicTransformHelper<MyType>(this));
|
||||
}
|
||||
|
||||
template<typename Signature>
|
||||
VTKM_CONT_EXPORT
|
||||
void DynamicTransformInvoke(
|
||||
const vtkm::internal::FunctionInterface<Signature> ¶meters) const
|
||||
{
|
||||
// TODO: Check parameters
|
||||
static const vtkm::IdComponent INPUT_DOMAIN_INDEX =
|
||||
WorkletType::InputDomain::INDEX;
|
||||
reinterpret_cast<const DerivedClass *>(this)->DoInvoke(
|
||||
vtkm::internal::make_Invocation<INPUT_DOMAIN_INDEX>(
|
||||
parameters, ControlInterface(), ExecutionInterface()));
|
||||
}
|
||||
|
||||
public:
|
||||
// Implementation of the Invoke method is in this generated file.
|
||||
#include <vtkm/worklet/internal/DispatcherBaseDetailInvoke.h>
|
||||
|
||||
protected:
|
||||
VTKM_CONT_EXPORT
|
||||
DispatcherBase(const WorkletType &worklet) : Worklet(worklet) { }
|
||||
|
||||
template<typename Invocation>
|
||||
VTKM_CONT_EXPORT
|
||||
void BasicInvoke(const Invocation &invocation, vtkm::Id numInstances) const
|
||||
{
|
||||
this->InvokeTransportParameters(invocation, numInstances);
|
||||
}
|
||||
|
||||
WorkletType Worklet;
|
||||
|
||||
private:
|
||||
// These are not implemented. Dispatchers cannot be copied.
|
||||
DispatcherBase(const MyType &);
|
||||
void operator=(const MyType &);
|
||||
|
||||
template<typename Invocation>
|
||||
VTKM_CONT_EXPORT
|
||||
void InvokeTransportParameters(const Invocation &invocation,
|
||||
vtkm::Id numInstances) const
|
||||
{
|
||||
// The first step in invoking a worklet is transport the arguments to the
|
||||
// execution environment. The invocation object passed to this function
|
||||
// contains the parameters passed to Invoke in the control environment. We
|
||||
// will use the template magic in the FunctionInterface class to invoke the
|
||||
// appropriate Transport class on each parameter to get a list of execution
|
||||
// objects (corresponding to the arguments of the Invoke in the control
|
||||
// environment) in a FunctionInterface.
|
||||
|
||||
// The Transport relies on both the ControlSignature tag and the control
|
||||
// object itself. To make it easier to work with each parameter, use the
|
||||
// zip mechanism of FunctionInterface to combine the separate function
|
||||
// interfaces of the ControlSignature and the parameters into one. This
|
||||
// will make a Function interface with each parameter being a Pair
|
||||
// containing both the ControlSignature tag and the control object itself.
|
||||
typedef typename vtkm::internal::FunctionInterfaceZipType<
|
||||
typename Invocation::ControlInterface,
|
||||
typename Invocation::ParameterInterface>::type ZippedInterface;
|
||||
ZippedInterface zippedInterface =
|
||||
vtkm::internal::make_FunctionInterfaceZip(
|
||||
typename Invocation::ControlInterface(), invocation.Parameters);
|
||||
|
||||
// Use the StaticTransform mechanism to run the
|
||||
// DispatcherBaseTransportFunctor on each parameter of the zipped
|
||||
// interface. This functor will in turn run the appropriate Transform on
|
||||
// the parameter and return the associated execution object. The end result
|
||||
// of the transform is a FunctionInterface containing execution objects
|
||||
// corresponding to each Invoke argument.
|
||||
typedef detail::DispatcherBaseTransportFunctor<Device> TransportFunctor;
|
||||
typedef typename ZippedInterface::template StaticTransformType<
|
||||
TransportFunctor>::type ExecObjectParameters;
|
||||
ExecObjectParameters execObjectParameters =
|
||||
zippedInterface.StaticTransformCont(TransportFunctor(numInstances));
|
||||
|
||||
// Replace the parameters in the invocation with the execution object and
|
||||
// pass to next step of Invoke.
|
||||
this->InvokeSchedule(invocation.ChangeParameters(execObjectParameters),
|
||||
numInstances);
|
||||
}
|
||||
|
||||
template<typename Invocation>
|
||||
VTKM_CONT_EXPORT
|
||||
void InvokeSchedule(const Invocation &invocation, vtkm::Id numInstances) const
|
||||
{
|
||||
// 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);
|
||||
|
||||
typedef vtkm::cont::DeviceAdapterAlgorithm<Device> Algorithm;
|
||||
Algorithm::Schedule(workletFunctor, numInstances);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::worklet::internal
|
||||
|
||||
#endif //vtk_m_worklet_internal_DispatcherBase_h
|
143
vtkm/worklet/internal/DispatcherBaseDetailInvoke.h
Normal file
143
vtkm/worklet/internal/DispatcherBaseDetailInvoke.h
Normal file
@ -0,0 +1,143 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
// **** DO NOT EDIT THIS FILE!!! ****
|
||||
// This file is automatically generated by FunctionInterfaceDetailPre.h.in
|
||||
|
||||
#if !defined(vtk_m_worklet_internal_DispatcherBase_h)
|
||||
#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h
|
||||
#endif
|
||||
|
||||
// Note that this file is included from the middle of the DispatcherBase.h
|
||||
// class to provide the implementation of the Invoke method, which requires
|
||||
// variable length template args. If we choose to support C++11 variable
|
||||
// template arguments, then this could all be replaced efficiently with a
|
||||
// single method with a variadic template function that calls
|
||||
// make_FunctionInterface.
|
||||
|
||||
|
||||
|
||||
template<typename T1>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7,
|
||||
typename T8>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7,a8));
|
||||
}
|
||||
|
||||
template<typename T1,
|
||||
typename T2,
|
||||
typename T3,
|
||||
typename T4,
|
||||
typename T5,
|
||||
typename T6,
|
||||
typename T7,
|
||||
typename T8,
|
||||
typename T9>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7,a8,a9));
|
||||
}
|
||||
|
86
vtkm/worklet/internal/DispatcherBaseDetailInvoke.h.in
Normal file
86
vtkm/worklet/internal/DispatcherBaseDetailInvoke.h.in
Normal file
@ -0,0 +1,86 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
$# This file uses the pyexpander macro processing utility to build the
|
||||
$# FunctionInterface facilities that use a variable number of arguments.
|
||||
$# Information, documentation, and downloads for pyexpander can be found at:
|
||||
$#
|
||||
$# http://pyexpander.sourceforge.net/
|
||||
$#
|
||||
$# To build the source code, execute the following (after installing
|
||||
$# pyexpander, of course):
|
||||
$#
|
||||
$# expander.py DispatcherBaseDetailInvoke.h.in > DispatcherBaseDetailInvoke.h
|
||||
$#
|
||||
$# Ignore the following comment. It is meant for the generated file.
|
||||
// **** DO NOT EDIT THIS FILE!!! ****
|
||||
// This file is automatically generated by FunctionInterfaceDetailPre.h.in
|
||||
|
||||
#if !defined(vtk_m_worklet_internal_DispatcherBase_h)
|
||||
#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h
|
||||
#endif
|
||||
|
||||
// Note that this file is included from the middle of the DispatcherBase.h
|
||||
// class to provide the implementation of the Invoke method, which requires
|
||||
// variable length template args. If we choose to support C++11 variable
|
||||
// template arguments, then this could all be replaced efficiently with a
|
||||
// single method with a variadic template function that calls
|
||||
// make_FunctionInterface.
|
||||
|
||||
$py(max_parameters=9)\
|
||||
|
||||
$# Python commands used in template expansion.
|
||||
$py(
|
||||
def template_params(num_params, name='T', start=1, default=''):
|
||||
if num_params < start:
|
||||
return ''
|
||||
result = 'typename %s%d%s' % (name, start, default)
|
||||
for param in xrange(start+1, num_params+1):
|
||||
result += ',\n typename %s%d%s' % (name, param, default)
|
||||
return result
|
||||
|
||||
def function_params(num_params, typename='T', argname='a', start=1):
|
||||
if num_params < start:
|
||||
return ''
|
||||
result = '%s%d %s%d' % (typename, start, argname, start)
|
||||
for param in xrange(start+1, num_params+1):
|
||||
result += ', %s%d %s%d' % (typename, param, argname, param)
|
||||
return result
|
||||
|
||||
def arg_list(num_params, argname='a', start=1):
|
||||
if num_params < start:
|
||||
return ''
|
||||
result = '%s%d' % (argname, start)
|
||||
for param in xrange(start+1, num_params+1):
|
||||
result += ',%s%d' % (argname, param)
|
||||
return result
|
||||
)\
|
||||
$#
|
||||
$extend(template_params, function_params, arg_list)\
|
||||
|
||||
$for(num_params in xrange(1, max_parameters+1))\
|
||||
template<$template_params(num_params)>
|
||||
VTKM_CONT_EXPORT
|
||||
void Invoke($function_params(num_params)) const
|
||||
{
|
||||
this->StartInvoke(
|
||||
vtkm::internal::make_FunctionInterface<void>($arg_list(num_params)));
|
||||
}
|
||||
|
||||
$endfor\
|
25
vtkm/worklet/internal/testing/CMakeLists.txt
Normal file
25
vtkm/worklet/internal/testing/CMakeLists.txt
Normal file
@ -0,0 +1,25 @@
|
||||
##============================================================================
|
||||
## 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.
|
||||
##============================================================================
|
||||
|
||||
set(unit_tests
|
||||
UnitTestDispatcherBase.cxx
|
||||
)
|
||||
|
||||
vtkm_unit_tests(SOURCES ${unit_tests})
|
262
vtkm/worklet/internal/testing/UnitTestDispatcherBase.cxx
Normal file
262
vtkm/worklet/internal/testing/UnitTestDispatcherBase.cxx
Normal file
@ -0,0 +1,262 @@
|
||||
//============================================================================
|
||||
// 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/worklet/internal/DispatcherBase.h>
|
||||
|
||||
#include <vtkm/cont/DeviceAdapterSerial.h>
|
||||
|
||||
#include <vtkm/worklet/internal/WorkletBase.h>
|
||||
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
namespace {
|
||||
|
||||
typedef vtkm::cont::DeviceAdapterTagSerial Device;
|
||||
|
||||
static const vtkm::Id ARRAY_SIZE = 10;
|
||||
|
||||
struct TestExecObject
|
||||
{
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
TestExecObject() : Array(NULL) { }
|
||||
|
||||
VTKM_EXEC_CONT_EXPORT
|
||||
TestExecObject(vtkm::Id *array) : Array(array) { }
|
||||
|
||||
vtkm::Id *Array;
|
||||
};
|
||||
|
||||
struct TestTransportTag { };
|
||||
struct TestFetchTagInput { };
|
||||
struct TestFetchTagOutput { };
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm {
|
||||
namespace cont {
|
||||
namespace arg {
|
||||
|
||||
template<>
|
||||
struct Transport<TestTransportTag, vtkm::Id *, Device>
|
||||
{
|
||||
typedef TestExecObject ExecObjectType;
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
ExecObjectType operator()(vtkm::Id *contData, vtkm::Id size) const
|
||||
{
|
||||
VTKM_TEST_ASSERT(size == ARRAY_SIZE,
|
||||
"Got unexpected size in test transport.");
|
||||
return ExecObjectType(contData);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::arg
|
||||
|
||||
namespace vtkm {
|
||||
namespace exec {
|
||||
namespace arg {
|
||||
|
||||
template<typename Invocation, vtkm::IdComponent ParameterIndex>
|
||||
struct Fetch<TestFetchTagInput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
ValueType Load(vtkm::Id index, const Invocation &invocation) const {
|
||||
return invocation.Parameters.
|
||||
template GetParameter<ParameterIndex>().Array[index];
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void Store(vtkm::Id, const Invocation &, ValueType) const {
|
||||
// No-op
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Invocation, vtkm::IdComponent ParameterIndex>
|
||||
struct Fetch<TestFetchTagOutput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
|
||||
{
|
||||
typedef vtkm::Id ValueType;
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
ValueType Load(vtkm::Id, const Invocation &) const {
|
||||
// No-op
|
||||
return ValueType();
|
||||
}
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void Store(vtkm::Id index,
|
||||
const Invocation &invocation,
|
||||
ValueType value) const {
|
||||
invocation.Parameters.template GetParameter<ParameterIndex>().Array[index] =
|
||||
value;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // vtkm::exec::arg
|
||||
|
||||
namespace {
|
||||
|
||||
class TestWorkletBase : public vtkm::worklet::internal::WorkletBase
|
||||
{
|
||||
public:
|
||||
struct TestIn {
|
||||
typedef TestTransportTag TransportTag;
|
||||
typedef TestFetchTagInput FetchTag;
|
||||
};
|
||||
struct TestOut {
|
||||
typedef TestTransportTag TransportTag;
|
||||
typedef TestFetchTagOutput FetchTag;
|
||||
};
|
||||
};
|
||||
|
||||
class TestWorklet : public TestWorkletBase
|
||||
{
|
||||
public:
|
||||
typedef void ControlSignature(TestIn, TestOut);
|
||||
typedef _2 ExecutionSignature(_1, WorkIndex);
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
vtkm::Id operator()(vtkm::Id value, vtkm::Id index) const
|
||||
{
|
||||
VTKM_TEST_ASSERT(value == TestValue(index, vtkm::Id()),
|
||||
"Got bad value in worklet.");
|
||||
return TestValue(index, vtkm::Id()) + 1000;
|
||||
}
|
||||
};
|
||||
|
||||
#define ERROR_MESSAGE "Expected worklet error."
|
||||
|
||||
class TestErrorWorklet : public TestWorkletBase
|
||||
{
|
||||
public:
|
||||
typedef void ControlSignature(TestIn, TestOut);
|
||||
typedef void ExecutionSignature(_1, _2);
|
||||
|
||||
VTKM_EXEC_EXPORT
|
||||
void operator()(vtkm::Id, vtkm::Id) const
|
||||
{
|
||||
this->RaiseError(ERROR_MESSAGE);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename WorkletType>
|
||||
class TestDispatcher :
|
||||
public vtkm::worklet::internal::DispatcherBase<
|
||||
TestDispatcher<WorkletType>,
|
||||
WorkletType,
|
||||
TestWorkletBase,
|
||||
Device>
|
||||
{
|
||||
typedef vtkm::worklet::internal::DispatcherBase<
|
||||
TestDispatcher<WorkletType>,
|
||||
WorkletType,
|
||||
TestWorkletBase,
|
||||
Device> Superclass;
|
||||
typedef vtkm::internal::FunctionInterface<void(vtkm::Id *, vtkm::Id *)>
|
||||
ParameterInterface;
|
||||
typedef vtkm::internal::Invocation<
|
||||
ParameterInterface,
|
||||
typename Superclass::ControlInterface,
|
||||
typename Superclass::ExecutionInterface,
|
||||
1> Invocation;
|
||||
public:
|
||||
VTKM_CONT_EXPORT
|
||||
TestDispatcher(const WorkletType &worklet = WorkletType())
|
||||
: Superclass(worklet) { }
|
||||
|
||||
VTKM_CONT_EXPORT
|
||||
void DoInvoke(const Invocation &invocation) const
|
||||
{
|
||||
std::cout << "In TestDispatcher::DoInvoke()" << std::endl;
|
||||
this->BasicInvoke(invocation, ARRAY_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
WorkletType Worklet;
|
||||
};
|
||||
|
||||
void TestBasicInvoke()
|
||||
{
|
||||
std::cout << "Set up data." << std::endl;
|
||||
vtkm::Id inputArray[ARRAY_SIZE];
|
||||
vtkm::Id outputArray[ARRAY_SIZE];
|
||||
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
inputArray[index] = TestValue(index, vtkm::Id());
|
||||
outputArray[index] = 0xDEADDEAD;
|
||||
}
|
||||
|
||||
std::cout << "Create and run dispatcher." << std::endl;
|
||||
TestDispatcher<TestWorklet> dispatcher;
|
||||
dispatcher.Invoke(inputArray, outputArray);
|
||||
|
||||
std::cout << "Check output of invoke." << std::endl;
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
VTKM_TEST_ASSERT(outputArray[index] == TestValue(index, vtkm::Id()) + 1000,
|
||||
"Got bad value from testing.");
|
||||
}
|
||||
}
|
||||
|
||||
void TestInvokeWithError()
|
||||
{
|
||||
std::cout << "Set up data." << std::endl;
|
||||
vtkm::Id inputArray[ARRAY_SIZE];
|
||||
vtkm::Id outputArray[ARRAY_SIZE];
|
||||
|
||||
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
|
||||
{
|
||||
inputArray[index] = TestValue(index, vtkm::Id());
|
||||
outputArray[index] = 0xDEADDEAD;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::cout << "Create and run dispatcher that raises error." << std::endl;
|
||||
TestDispatcher<TestErrorWorklet> dispatcher;
|
||||
dispatcher.Invoke(inputArray, outputArray);
|
||||
VTKM_TEST_FAIL("Exception not thrown.");
|
||||
}
|
||||
catch (vtkm::cont::ErrorExecution error)
|
||||
{
|
||||
std::cout << "Got expected exception." << std::endl;
|
||||
VTKM_TEST_ASSERT(error.GetMessage() == ERROR_MESSAGE,
|
||||
"Got unexpected error message.");
|
||||
}
|
||||
}
|
||||
|
||||
void TestDispatcherBase()
|
||||
{
|
||||
TestBasicInvoke();
|
||||
TestInvokeWithError();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestDispatcherBase(int, char *[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestDispatcherBase);
|
||||
}
|
Loading…
Reference in New Issue
Block a user