WorkletInvokeFunctorDetail.h.in 10.9 KB
Newer Older
1
2
3
4
5
6
7
8
//============================================================================
//  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.
//
Kenneth Moreland's avatar
Kenneth Moreland committed
9
//  Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
10
//  Copyright 2014 UT-Battelle, LLC.
11
//  Copyright 2014 Los Alamos National Security.
12
//
Kenneth Moreland's avatar
Kenneth Moreland committed
13
//  Under the terms of Contract DE-NA0003525 with NTESS,
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//  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

43
44
#if !defined(vtk_m_exec_internal_TaskSingular_h) && !defined(vtk_m_exec_internal_TaskTiling_h) &&  \\
  !defined(VTKM_TEST_HEADER_BUILD)
45
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h or TaskTiling.h
46
47
48
49
50
51
52
53
#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
54
$py(max_parameters=20)\
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#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):
84
    result += ',\n          typename %s' % ptype(param, name)
85
86
87
88
89
90
91
  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):
92
    result += ', %s' % ptype(param, name)
93
94
95
96
97
98
99
100
  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):
101
    result += ', %s' % pname(param, name)
102
103
104
105
106
  return result
)\
$#
$extend(comma_if, ptype, pname, template_params, signature, arg_list)\

107
108
109
110
111
112
113
114
namespace vtkm
{
namespace exec
{
namespace internal
{
namespace detail
{
115
116
117
118

/// 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.
119
120
121
template <typename ThreadIndicesType,
          typename Invocation,
          vtkm::IdComponent ExecutionParameterIndex>
122
123
struct InvocationToFetch
{
124
125
  using ExecutionSignatureTag =
    typename Invocation::ExecutionInterface::template ParameterType<ExecutionParameterIndex>::type;
126
127
128
129

  // 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.
130
  static const vtkm::IdComponent ControlParameterIndex = ExecutionSignatureTag::INDEX;
131
  using AspectTag = typename ExecutionSignatureTag::AspectTag;
132
133
134

  // Find the fetch tag from the control signature tag pointed to by
  // ParameterIndex.
135
136
137
  using ControlInterface = typename Invocation::ControlInterface;
  using ControlSignatureTag = typename ControlInterface::template ParameterType<ControlParameterIndex>::type;
  using FetchTag = typename ControlSignatureTag::FetchTag;
138

139
140
  using ExecObjectType =
    typename Invocation::ParameterInterface::template ParameterType<ControlParameterIndex>::type;
141

142
  using type = vtkm::exec::arg::Fetch<FetchTag, AspectTag, ThreadIndicesType, ExecObjectType>;
143
144
};

145
146
// clang-format off

147
$for(num_params in range(1, max_parameters+1))\
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
template <typename WorkletType,
          typename ParameterInterface,
          typename ControlInterface,
          vtkm::IdComponent InputDomainIndex,
          typename OutputToInputMapType,
          typename VisitArrayType,
          typename ThreadIndicesType,
          $template_params(num_params)>
VTKM_EXEC void DoWorkletInvokeFunctor(
  const WorkletType& worklet,
  const vtkm::internal::Invocation<ParameterInterface,
                                   ControlInterface,
                                   vtkm::internal::FunctionInterface<$signature(num_params)>,
                                   InputDomainIndex,
                                   OutputToInputMapType,
                                   VisitArrayType>& invocation,
  const ThreadIndicesType& threadIndices)
165
{
166
167
168
169
170
171
  using Invocation =  vtkm::internal::Invocation<ParameterInterface,
                                                 ControlInterface,
                                                 vtkm::internal::FunctionInterface<$signature(num_params)>,
                                                 InputDomainIndex,
                                                 OutputToInputMapType,
                                                 VisitArrayType>;
172
173
$for(param_index in range(1, num_params+1))\

174
175
  using FetchInfo$(param_index) = InvocationToFetch<ThreadIndicesType, Invocation, $(param_index)>;
  using FetchType$(param_index) = typename FetchInfo$(param_index)::type;
176
  FetchType$(param_index) fetch$(param_index);
177
  typename FetchType$(param_index)::ValueType $pname(param_index) =
178
179
    fetch$(param_index).Load(threadIndices,
                invocation.Parameters.template GetParameter<FetchInfo$(param_index)::ControlParameterIndex>());
180
181
$endfor\

182
183
  using FetchInfo0 = InvocationToFetch<ThreadIndicesType, Invocation, 0>;
  using ReturnFetchType = typename FetchInfo0::type;
184
  ReturnFetchType returnFetch;
185
186
187
188
189
190
191
192
193
  // If you got a compile error on the following line, it probably means that
  // the operator() of a worklet does not match the definition expected. One
  // common problem is that the operator() method must be declared const. Check
  // to make sure the "const" keyword is after parameters. Another common
  // problem is that the type of one or more parameters is incompatible with
  // the actual type that VTK-m creates in the execution environment. Make sure
  // that the types of the worklet operator() parameters match those in the
  // ExecutionSignature. The compiler error might help you narrow down which
  // parameter is wrong and the types that did not match.
194
  auto $pname(0) = typename ReturnFetchType::ValueType(worklet($arg_list(num_params)));
195

196
  returnFetch.Store(
197
198
199
    threadIndices,
    invocation.Parameters.template GetParameter<FetchInfo0::ControlParameterIndex>(),
    $pname(0));
200
201

$for(param_index in range(1, num_params+1))\
202
203
204
  fetch$(param_index).Store(threadIndices,
               invocation.Parameters.template GetParameter<FetchInfo$(param_index)::ControlParameterIndex>(),
               $pname(param_index));
205
206
207
$endfor\
}

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
template <typename WorkletType,
          typename ParameterInterface,
          typename ControlInterface,
          vtkm::IdComponent InputDomainIndex,
          typename OutputToInputMapType,
          typename VisitArrayType,
          typename ThreadIndicesType,
          $template_params(num_params, start=1)>
VTKM_EXEC void DoWorkletInvokeFunctor(
  const WorkletType& worklet,
  const vtkm::internal::Invocation<ParameterInterface,
                                   ControlInterface,
                                   vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
                                   InputDomainIndex,
                                   OutputToInputMapType,
                                   VisitArrayType>& invocation,
  const ThreadIndicesType& threadIndices)
225
{
226
227
228
229
230
231
232
  typedef vtkm::internal::Invocation<ParameterInterface,
                                     ControlInterface,
                                     vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
                                     InputDomainIndex,
                                     OutputToInputMapType,
                                     VisitArrayType>
    Invocation;
233
234
$for(param_index in range(1, num_params+1))\

235
236
  using FetchInfo$(param_index) = InvocationToFetch<ThreadIndicesType, Invocation, $(param_index)>;
  using FetchType$(param_index) = typename FetchInfo$(param_index)::type;
237
  FetchType$(param_index) fetch$(param_index);
238
  typename FetchType$(param_index)::ValueType $pname(param_index) =
239
240
    fetch$(param_index).Load(threadIndices,
                invocation.Parameters.template GetParameter<FetchInfo$(param_index)::ControlParameterIndex>());
241
242
$endfor\

243
244
245
246
247
248
249
250
251
  // If you got a compile error on the following line, it probably means that
  // the operator() of a worklet does not match the definition expected. One
  // common problem is that the operator() method must be declared const. Check
  // to make sure the "const" keyword is after parameters. Another common
  // problem is that the type of one or more parameters is incompatible with
  // the actual type that VTK-m creates in the execution environment. Make sure
  // that the types of the worklet operator() parameters match those in the
  // ExecutionSignature. The compiler error might help you narrow down which
  // parameter is wrong and the types that did not match.
252
253
254
  worklet($arg_list(num_params));

$for(param_index in range(1, num_params+1))\
255
256
257
  fetch$(param_index).Store(threadIndices,
               invocation.Parameters.template GetParameter<FetchInfo$(param_index)::ControlParameterIndex>(),
               $pname(param_index));
258
259
260
261
$endfor\
}

$endfor\
262
// clang-format on
263
264
265
266
267
268
}
}
}
} // namespace vtkm::exec::internal::detail

#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h