//============================================================================ // 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 #include #include #include $# 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 struct InvocationToFetch { using ExecutionSignatureTag = typename Invocation::ExecutionInterface::template ParameterType::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::type>::type; using FetchTag = typename ControlSignatureTag::FetchTag; using ExecObjectType = typename std::conditional< ControlParameterIndex == 0, typename Invocation::DeviceAdapterTag, typename Invocation::ParameterInterface::template ParameterType::type>::type; using type = vtkm::exec::arg::Fetch; 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(invocation.Parameters); } VTKM_EXEC static ExecObjectType GetParameter(const Invocation& invocation) { return GetParameterImpl(invocation, std::integral_constant()); } }; // clang-format off $for(num_params in range(1, max_parameters+1))\ template VTKM_EXEC void DoWorkletInvokeFunctor( const WorkletType& worklet, const vtkm::internal::Invocation, InputDomainIndex, OutputToInputMapType, VisitArrayType, ThreadToOutputMapType, DeviceAdapterTag>& invocation, const ThreadIndicesType& threadIndices) { using Invocation = vtkm::internal::Invocation, InputDomainIndex, OutputToInputMapType, VisitArrayType, ThreadToOutputMapType, DeviceAdapterTag>; $for(param_index in range(1, num_params+1))\ using FetchInfo$(param_index) = InvocationToFetch; using FetchType$(param_index) = typename FetchInfo$(param_index)::type; FetchType$(param_index) fetch$(param_index); typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(threadIndices, FetchInfo$(param_index)::GetParameter(invocation)); $endfor\ using FetchInfo0 = InvocationToFetch; 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) = typename ReturnFetchType::ValueType(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 VTKM_EXEC void DoWorkletInvokeFunctor( const WorkletType& worklet, const vtkm::internal::Invocation, InputDomainIndex, OutputToInputMapType, VisitArrayType, ThreadToOutputMapType, DeviceAdapterTag>& invocation, const ThreadIndicesType& threadIndices) { using Invocation = vtkm::internal::Invocation, InputDomainIndex, OutputToInputMapType, VisitArrayType, ThreadToOutputMapType, DeviceAdapterTag>; $for(param_index in range(1, num_params+1))\ using FetchInfo$(param_index) = InvocationToFetch; using FetchType$(param_index) = typename FetchInfo$(param_index)::type; FetchType$(param_index) fetch$(param_index); typename FetchType$(param_index)::ValueType $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