vtk-m/vtkm/exec/internal/WorkletInvokeFunctorDetail.h.in
Vicente Adolfo Bolea Sanchez d0396e2a40 relaxes ThreadIndicesType across multiple worklets fetchs
This change is needed for being able to use different thread indices types
without changing Fetchs. Basically decoupling those two areas.

1. This commit removes concrete specialization instantiations of
   ThreadIndicesTypes in all of the Fetch's specializations.

2. It also moves the ThreadIndicesType template parameter from the Fetch
   struct to a template parameter in their methods Load/Store.

Signed-off-by: Vicente Adolfo Bolea Sanchez <vicente.bolea@kitware.com>
2020-04-24 17:39:31 -04:00

293 lines
12 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.
//============================================================================
$# 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_TaskSingular_h) && \\
!defined(vtk_m_exec_internal_TaskTiling_h) && \\
!defined(vtk_m_exec_cuda_internal_TaskStrided_h) && \\
!defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from TaskSingular.h, TaskTiling.h, TaskStrided.h
#endif
#include <vtkm/internal/FunctionInterface.h>
#include <vtkm/internal/Invocation.h>
#include <vtkm/exec/arg/Fetch.h>
#include <vtkm/exec/arg/FetchTagExecObject.h>
$# This needs to match the max_parameters in FunctionInterfaceDetailPre.h.in
$py(max_parameters=20)\
#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 range(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 range(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 range(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
{
struct DummyDeviceControlSignatureTag
{
using FetchTag = vtkm::exec::arg::FetchTagExecObject;
};
/// 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 ThreadIndicesType,
typename Invocation,
vtkm::IdComponent ExecutionParameterIndex>
struct InvocationToFetch
{
using ExecutionSignatureTag =
typename Invocation::ExecutionInterface::template ParameterType<ExecutionParameterIndex>::type;
// 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 constexpr vtkm::IdComponent ControlParameterIndex = ExecutionSignatureTag::INDEX;
using AspectTag = typename ExecutionSignatureTag::AspectTag;
// Find the fetch tag from the control signature tag pointed to by
// ParameterIndex. Note that ControlParameterIndex of 0 is reserved
// for getting the device adapter tag.
using ControlInterface = typename Invocation::ControlInterface;
using ControlSignatureTag =
typename std::conditional<
ControlParameterIndex == 0,
DummyDeviceControlSignatureTag,
typename ControlInterface::template ParameterType<ControlParameterIndex>::type>::type;
using FetchTag = typename ControlSignatureTag::FetchTag;
using ExecObjectType =
typename std::conditional<
ControlParameterIndex == 0,
typename Invocation::DeviceAdapterTag,
typename Invocation::ParameterInterface::template ParameterType<ControlParameterIndex>::type>::type;
using type = vtkm::exec::arg::Fetch<FetchTag, AspectTag, ExecObjectType>;
VTKM_EXEC static ExecObjectType GetParameterImpl(const Invocation&, std::true_type)
{
return typename Invocation::DeviceAdapterTag();
}
VTKM_EXEC static ExecObjectType GetParameterImpl(const Invocation& invocation, std::false_type)
{
return vtkm::internal::ParameterGet<ControlParameterIndex>(invocation.Parameters);
}
VTKM_EXEC static ExecObjectType GetParameter(const Invocation& invocation)
{
return GetParameterImpl(invocation, std::integral_constant<bool, ControlParameterIndex == 0>());
}
};
// clang-format off
$for(num_params in range(1, max_parameters+1))\
template <typename WorkletType,
typename ParameterInterface,
typename ControlInterface,
vtkm::IdComponent InputDomainIndex,
typename OutputToInputMapType,
typename VisitArrayType,
typename ThreadToOutputMapType,
typename DeviceAdapterTag,
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,
ThreadToOutputMapType,
DeviceAdapterTag>& invocation,
const ThreadIndicesType& threadIndices)
{
using Invocation = vtkm::internal::Invocation<ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params)>,
InputDomainIndex,
OutputToInputMapType,
VisitArrayType,
ThreadToOutputMapType,
DeviceAdapterTag>;
$for(param_index in range(1, num_params+1))\
using FetchInfo$(param_index) = InvocationToFetch<ThreadIndicesType, Invocation, $(param_index)>;
using FetchType$(param_index) = typename FetchInfo$(param_index)::type;
FetchType$(param_index) fetch$(param_index);
auto $pname(param_index) =
fetch$(param_index).Load(threadIndices, FetchInfo$(param_index)::GetParameter(invocation));
$endfor\
using FetchInfo0 = InvocationToFetch<ThreadIndicesType, Invocation, 0>;
using ReturnFetchType = typename FetchInfo0::type;
ReturnFetchType returnFetch;
// 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.
auto $pname(0) = worklet($arg_list(num_params));
$for(param_index in range(1, num_params+1))\
fetch$(param_index).Store(threadIndices, FetchInfo$(param_index)::GetParameter(invocation), $pname(param_index));
$endfor\
returnFetch.Store(threadIndices, FetchInfo0::GetParameter(invocation), $pname(0));
}
template <typename WorkletType,
typename ParameterInterface,
typename ControlInterface,
vtkm::IdComponent InputDomainIndex,
typename OutputToInputMapType,
typename VisitArrayType,
typename ThreadToOutputMapType,
typename DeviceAdapterTag,
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,
ThreadToOutputMapType,
DeviceAdapterTag>& invocation,
const ThreadIndicesType& threadIndices)
{
using Invocation =
vtkm::internal::Invocation<ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
InputDomainIndex,
OutputToInputMapType,
VisitArrayType,
ThreadToOutputMapType,
DeviceAdapterTag>;
$for(param_index in range(1, num_params+1))\
using FetchInfo$(param_index) = InvocationToFetch<ThreadIndicesType, Invocation, $(param_index)>;
using FetchType$(param_index) = typename FetchInfo$(param_index)::type;
FetchType$(param_index) fetch$(param_index);
auto $pname(param_index) =
fetch$(param_index).Load(threadIndices, FetchInfo$(param_index)::GetParameter(invocation));
$endfor\
// 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.
worklet($arg_list(num_params));
$for(param_index in range(1, num_params+1))\
fetch$(param_index).Store(threadIndices, FetchInfo$(param_index)::GetParameter(invocation), $pname(param_index));
$endfor\
}
$endfor\
// clang-format on
}
}
}
} // namespace vtkm::exec::internal::detail
#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h