vtk-m2/vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in
Kenneth Moreland 53a454fe77 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.
2014-10-21 11:49:23 -06:00

220 lines
7.5 KiB
C

//============================================================================
// 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