10 #ifndef vtk_m_worklet_internal_DispatcherBase_h 
   11 #define vtk_m_worklet_internal_DispatcherBase_h 
   34 #include <vtkmstd/integer_sequence.h> 
   35 #include <vtkmstd/is_trivial.h> 
   46 template <
typename Domain>
 
   47 inline auto SchedulingRange(
const Domain& inputDomain) -> decltype(inputDomain.GetNumberOfValues())
 
   49   return inputDomain.GetNumberOfValues();
 
   52 template <
typename Domain>
 
   53 inline auto SchedulingRange(
const Domain* 
const inputDomain)
 
   54   -> decltype(inputDomain->GetNumberOfValues())
 
   56   return inputDomain->GetNumberOfValues();
 
   59 template <
typename Domain, 
typename SchedulingRangeType>
 
   60 inline auto SchedulingRange(
const Domain& inputDomain, SchedulingRangeType type)
 
   61   -> decltype(inputDomain.GetSchedulingRange(type))
 
   63   return inputDomain.GetSchedulingRange(type);
 
   66 template <
typename Domain, 
typename SchedulingRangeType>
 
   67 inline auto SchedulingRange(
const Domain* 
const inputDomain, SchedulingRangeType type)
 
   68   -> decltype(inputDomain->GetSchedulingRange(type))
 
   70   return inputDomain->GetSchedulingRange(type);
 
   84 inline void PrintFailureMessage(
int index)
 
   86   std::stringstream message;
 
   87   message << 
"Encountered bad type for parameter " << index
 
   88           << 
" when calling Invoke on a dispatcher.";
 
   92 inline void PrintNullPtrMessage(
int index, 
int mode)
 
   94   std::stringstream message;
 
   97     message << 
"Encountered nullptr for parameter " << index;
 
  101     message << 
"Encountered nullptr for " << index << 
" from last parameter ";
 
  103   message << 
" when calling Invoke on a dispatcher.";
 
  107 template <
typename T>
 
  108 inline void not_nullptr(T* ptr, 
int index, 
int mode = 0)
 
  112     PrintNullPtrMessage(index, mode);
 
  115 template <
typename T>
 
  116 inline void not_nullptr(T&&, 
int, 
int mode = 0)
 
  121 template <
typename T>
 
  122 inline T& as_ref(T* ptr)
 
  126 template <
typename T>
 
  127 inline T&& as_ref(T&& t)
 
  129   return std::forward<T>(t);
 
  133 template <
typename T, 
bool noError>
 
  134 struct ReportTypeOnError : std::integral_constant<bool, noError>
 
  138 template <
int Value, 
bool noError>
 
  139 struct ReportValueOnError : std::integral_constant<bool, noError>
 
  143 template <
typename Type>
 
  144 struct IsDynamicTypeImpl
 
  146   using T = vtkm::internal::remove_pointer_and_decay<Type>;
 
  147   using DynamicTag = 
typename vtkm::cont::internal::DynamicTransformTraits<T>::DynamicTag;
 
  149     typename std::is_same<DynamicTag, vtkm::cont::internal::DynamicTransformTagCastAndCall>::type;
 
  151 template <
typename T>
 
  152 using IsDynamicType = 
typename IsDynamicTypeImpl<T>::type;
 
  154 template <
typename SigTagList, 
typename ParamList, 
typename IndexSequence>
 
  155 struct ZipControlParamImpl;
 
  157 struct ZipControlParamImpl<
vtkm::List<SigTags...>,
 
  159                            vtkmstd::integer_sequence<vtkm::IdComponent, Indices...>>
 
  167 template <
typename SigTagList, 
typename ParamList, 
typename IndexSequence>
 
  168 using ZipControlParam = 
typename ZipControlParamImpl<SigTagList, ParamList, IndexSequence>::type;
 
  170 template <
typename WorkletType>
 
  171 struct ControlArgumentValidator
 
  173   template <
typename SigTag, 
typename Param, vtkm::IdComponent Index>
 
  174   void operator()(
vtkm::List<SigTag, Param, std::integral_constant<vtkm::IdComponent, Index>>)
 const 
  176     using T = std::remove_pointer_t<Param>;
 
  177     using TypeCheckTag = 
typename SigTag::TypeCheckTag;
 
  182       "If you get an error here, that means that your code has invoked a worklet," 
  183       " and one of the arguments of the Invoke is the wrong type. Each argument of the invoke" 
  184       " corresponds to a tag in the arguments of the ControlSignature of the worklet. If there" 
  185       " is a mismatch, then you get an error here (instead of where you called invoke). For" 
  186       " example, if the worklet has a control signature as ControlSignature(CellSetIn, ...) and" 
  187       " the first argument passed to the invoke is an ArrayHandle, you will get an error here" 
  188       " because you cannot use an ArrayHandle in place of a CellSetIn argument. (You need to use" 
  189       " a CellSet.) If the compiler supports it, the next few errors on the following lines of" 
  190       " code will give information about where the error actually occurred.");
 
  200     static_assert(ReportTypeOnError<WorkletType, isCorrect>::value,
 
  201                   "The first template argument to ReportTypeOnError is the worklet being invoked");
 
  202     static_assert(ReportValueOnError<Index, isCorrect>::value,
 
  203                   "The first template argument to ReportTypeOnError is the index of Invoke " 
  204                   "parameter (starting at index 1)");
 
  205     static_assert(ReportTypeOnError<T, isCorrect>::value,
 
  206                   "The first template argument to ReportTypeOnError is the type passed to Invoke");
 
  207     static_assert(ReportTypeOnError<TypeCheckTag, isCorrect>::value,
 
  208                   "The first template argument to ReportTypeOnError is the type check tag used");
 
  214 struct DispatcherBaseControlSignatureTagCheck
 
  216   template <
typename ControlSignatureTag, vtkm::IdComponent Index>
 
  222     using type = ControlSignatureTag;
 
  228 struct DispatcherBaseExecutionSignatureTagCheck
 
  230   template <
typename ExecutionSignatureTag, vtkm::IdComponent Index>
 
  236     using type = ExecutionSignatureTag;
 
  240 struct DispatcherBaseTryExecuteFunctor
 
  242   template <
typename Device, 
typename DispatcherBaseType, 
typename Invocation, 
typename RangeType>
 
  244                             const DispatcherBaseType* 
self,
 
  245                             Invocation& invocation,
 
  246                             const RangeType& dimensions)
 
  248     auto outputRange = 
self->Scatter.GetOutputRange(dimensions);
 
  249     self->InvokeTransportParameters(
 
  250       invocation, dimensions, outputRange, self->Mask.GetThreadRange(outputRange), device);
 
  257 template <
typename ControlInterface, vtkm::IdComponent Index>
 
  258 struct DispatcherBaseTransportInvokeTypes
 
  261   using ControlSignatureTag = 
typename ControlInterface::template ParameterType<Index>::type;
 
  262   using TransportTag = 
typename ControlSignatureTag::TransportTag;
 
  274   return range[0] * range[1] * range[2];
 
  279 template <
typename ControlInterface, 
typename InputDomainType, 
typename Device>
 
  280 struct DispatcherBaseTransportFunctor
 
  282   const InputDomainType& InputDomain; 
 
  291   template <
typename InputRangeType, 
typename OutputRangeType>
 
  292   VTKM_CONT DispatcherBaseTransportFunctor(
const InputDomainType& inputDomain,
 
  293                                            const InputRangeType& inputRange,
 
  294                                            const OutputRangeType& outputRange,
 
  296     : InputDomain(inputDomain)
 
  297     , InputRange(FlatRange(inputRange))
 
  298     , OutputRange(FlatRange(outputRange))
 
  304   template <
typename ControlParameter, vtkm::IdComponent Index>
 
  308       typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag;
 
  309     using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>;
 
  311     using type = 
typename std::decay<typename TransportType::ExecObjectType>::type;
 
  319     VTKM_IS_TRIVIALLY_COPYABLE(type);
 
  322   template <
typename ControlParameter, vtkm::IdComponent Index>
 
  323   VTKM_CONT typename ReturnType<ControlParameter, Index>::type operator()(
 
  324     ControlParameter&& invokeData,
 
  325     vtkm::internal::IndexTag<Index>)
 const 
  328       typename DispatcherBaseTransportInvokeTypes<ControlInterface, Index>::TransportTag;
 
  329     using T = vtkm::internal::remove_pointer_and_decay<ControlParameter>;
 
  332     not_nullptr(invokeData, 
Index);
 
  333     return transport(as_ref(invokeData),
 
  334                      as_ref(this->InputDomain),
 
  343   void operator=(
const DispatcherBaseTransportFunctor&) = 
delete;
 
  348 template <
typename L>
 
  349 struct ListRemoveFirstImpl;
 
  350 template <
typename T, 
typename... Ts>
 
  351 struct ListRemoveFirstImpl<
vtkm::List<T, Ts...>>
 
  355 template <
typename L>
 
  356 using ListRemoveFirst = 
typename ListRemoveFirstImpl<L>::type;
 
  359 template <std::
size_t LeftToProcess>
 
  360 struct for_each_dynamic_arg;
 
  362 template <std::
size_t LeftToProcess, 
typename TypeCheckTag>
 
  363 struct convert_arg_wrapper
 
  365   template <
typename T, 
typename... Args>
 
  366   void operator()(T&& t, Args&&... args)
 const 
  368     using Type = 
typename std::decay<T>::type;
 
  370       std::integral_constant<bool, vtkm::cont::arg::TypeCheck<TypeCheckTag, Type>::value>;
 
  371     this->WillContinue(valid(), std::forward<T>(t), std::forward<Args>(args)...);
 
  373   template <
typename T, 
typename... Args>
 
  374   void WillContinue(std::true_type, T&& t, Args&&... args)
 const 
  376     for_each_dynamic_arg<LeftToProcess - 1>()(std::forward<Args>(args)..., std::forward<T>(t));
 
  378   template <
typename... Args>
 
  379   void WillContinue(std::false_type, Args&&...)
 const 
  381     vtkm::worklet::internal::detail::PrintFailureMessage(LeftToProcess);
 
  385 template <std::size_t LeftToProcess,
 
  390 inline void convert_arg(vtkm::cont::internal::DynamicTransformTagStatic,
 
  393                         const Trampoline& trampoline,
 
  396   using popped_sig = ListRemoveFirst<ContParams>;
 
  397   for_each_dynamic_arg<LeftToProcess - 1>()(
 
  398     trampoline, popped_sig(), std::forward<Args>(args)..., std::forward<T>(t));
 
  401 template <std::size_t LeftToProcess,
 
  406 inline void convert_arg(vtkm::cont::internal::DynamicTransformTagCastAndCall,
 
  409                         const Trampoline& trampoline,
 
  413   using popped_sig = ListRemoveFirst<ContParams>;
 
  415   not_nullptr(t, LeftToProcess, 1);
 
  417                           convert_arg_wrapper<LeftToProcess, tag_check>(),
 
  420                           std::forward<Args>(args)...);
 
  423 template <std::
size_t LeftToProcess>
 
  424 struct for_each_dynamic_arg
 
  426   template <
typename Trampoline, 
typename ContParams, 
typename T, 
typename... Args>
 
  427   void operator()(
const Trampoline& trampoline, ContParams&& sig, T&& t, Args&&... args)
 const 
  430     using Type = vtkm::internal::remove_pointer_and_decay<T>;
 
  431     using tag = 
typename vtkm::cont::internal::DynamicTransformTraits<Type>::DynamicTag;
 
  433     convert_arg<LeftToProcess>(
 
  434       tag(), std::forward<T>(t), sig, trampoline, std::forward<Args>(args)...);
 
  439 struct for_each_dynamic_arg<0>
 
  441   template <
typename Trampoline, 
typename ContParams, 
typename... Args>
 
  442   void operator()(
const Trampoline& trampoline, ContParams&&, Args&&... args)
 const 
  444     trampoline.StartInvokeDynamic(std::false_type(), std::forward<Args>(args)...);
 
  448 template <
typename Trampoline, 
typename ContParams, 
typename... Args>
 
  449 inline void deduce(Trampoline&& trampoline, ContParams&& sig, Args&&... args)
 
  451   for_each_dynamic_arg<
sizeof...(Args)>()(std::forward<Trampoline>(trampoline), sig, args...);
 
  458 template <vtkm::IdComponent MaxIndexAllowed>
 
  459 struct PlaceholderValidator
 
  461   PlaceholderValidator() {}
 
  465   void operator()(vtkm::internal::meta::Type<vtkm::placeholders::Arg<N>>)
 const 
  467     static_assert(N <= MaxIndexAllowed,
 
  468                   "An argument in the execution signature" 
  469                   " (usually _2, _3, _4, etc.) refers to a control signature argument that" 
  470                   " does not exist. For example, you will get this error if you have _3 (or" 
  471                   " _4 or _5 or so on) as one of the execution signature arguments, but you" 
  472                   " have fewer than 3 (or 4 or 5 or so on) arguments in the control signature.");
 
  475   template <
typename DerivedType>
 
  476   void operator()(vtkm::internal::meta::Type<DerivedType>)
 const 
  484 template <
typename DerivedClass, 
typename WorkletType, 
typename BaseWorkletType>
 
  488   using MyType = DispatcherBase<DerivedClass, WorkletType, BaseWorkletType>;
 
  490   friend struct detail::for_each_dynamic_arg<0>;
 
  493   using ControlInterface =
 
  494     vtkm::internal::FunctionInterface<typename WorkletType::ControlSignature>;
 
  498   using ExecutionSignature =
 
  499     typename vtkm::placeholders::GetExecSig<WorkletType>::ExecutionSignature;
 
  500   using ExecutionInterface = vtkm::internal::FunctionInterface<ExecutionSignature>;
 
  507   using ControlSignatureCheck = 
typename ControlInterface::template StaticTransformType<
 
  508     detail::DispatcherBaseControlSignatureTagCheck>::type;
 
  509   using ExecutionSignatureCheck = 
typename ExecutionInterface::template StaticTransformType<
 
  510     detail::DispatcherBaseExecutionSignatureTagCheck>::type;
 
  512   template <
typename... Args>
 
  513   VTKM_CONT void StartInvoke(Args&&... args)
 const 
  515     using ParameterInterface =
 
  516       vtkm::internal::FunctionInterface<void(vtkm::internal::remove_cvref<Args>...)>;
 
  519                            "Dispatcher Invoke called with wrong number of arguments.");
 
  522       std::is_base_of<BaseWorkletType, WorkletType>::value,
 
  523       "The worklet being scheduled by this dispatcher doesn't match the type of the dispatcher");
 
  527     using ComponentSig = 
typename ExecutionInterface::ComponentSig;
 
  537     using ParamTypes = 
typename ParameterInterface::ParameterSig;
 
  540     this->StartInvokeDynamic(HasDynamicTypes(), std::forward<Args>(args)...);
 
  543   template <
typename... Args>
 
  544   VTKM_CONT void StartInvokeDynamic(std::true_type, Args&&... args)
 const 
  550     using ContParamsInfo =
 
  551       vtkm::internal::detail::FunctionSigInfo<typename WorkletType::ControlSignature>;
 
  552     typename ContParamsInfo::Parameters parameters;
 
  553     detail::deduce(*
this, parameters, std::forward<Args>(args)...);
 
  556   template <
typename... Args>
 
  557   VTKM_CONT void StartInvokeDynamic(std::false_type, Args&&... args)
 const 
  559     using ParameterInterface =
 
  560       vtkm::internal::FunctionInterface<void(vtkm::internal::remove_cvref<Args>...)>;
 
  565     using ParamTypes = 
typename ParameterInterface::ParameterSig;
 
  566     using ContSigTypes = 
typename vtkm::internal::detail::FunctionSigInfo<
 
  567       typename WorkletType::ControlSignature>::Parameters;
 
  568     using ParamZip = detail::ZipControlParam<
 
  571       vtkmstd::make_integer_sequence<vtkm::IdComponent, vtkm::ListSize<ParamTypes>::value>>;
 
  577       vtkm::internal::make_FunctionInterface<void, vtkm::internal::remove_cvref<Args>...>(args...);
 
  578     auto ivc = vtkm::internal::Invocation<ParameterInterface,
 
  581                                           WorkletType::InputDomain::INDEX,
 
  582                                           vtkm::internal::NullType,
 
  583                                           vtkm::internal::NullType>(
 
  584       fi, vtkm::internal::NullType{}, vtkm::internal::NullType{});
 
  585     static_cast<const DerivedClass*
>(
this)->DoInvoke(ivc);
 
  600   using ScatterType = 
typename WorkletType::ScatterType;
 
  601   using MaskType = 
typename WorkletType::MaskType;
 
  603   template <
typename... Args>
 
  604   VTKM_CONT void Invoke(Args&&... args)
 const 
  607                    "Invoking Worklet: '%s'",
 
  608                    vtkm::cont::TypeToString<DerivedClass>().c_str());
 
  609     this->StartInvoke(std::forward<Args>(args)...);
 
  618   DispatcherBase(
const WorkletType& worklet = WorkletType(),
 
  619                  const ScatterType& scatter = ScatterType(),
 
  620                  const MaskType& mask = MaskType())
 
  624     , Device(
vtkm::cont::DeviceAdapterTagAny())
 
  633   DispatcherBase(
const ScatterType& scatter, 
const MaskType& mask = MaskType())
 
  634     : Worklet(WorkletType())
 
  637     , Device(
vtkm::cont::DeviceAdapterTagAny())
 
  646   DispatcherBase(
const WorkletType& worklet,
 
  647                  const MaskType& mask,
 
  648                  const ScatterType& scatter = ScatterType())
 
  652     , Device(
vtkm::cont::DeviceAdapterTagAny())
 
  661   DispatcherBase(
const MaskType& mask, 
const ScatterType& scatter = ScatterType())
 
  662     : Worklet(WorkletType())
 
  665     , Device(
vtkm::cont::DeviceAdapterTagAny())
 
  669   friend struct internal::detail::DispatcherBaseTryExecuteFunctor;
 
  671   template <
typename Invocation>
 
  676                                      internal::detail::DispatcherBaseTryExecuteFunctor(),
 
  686   template <
typename Invocation>
 
  689     this->BasicInvoke(invocation, 
vtkm::Id3(dimensions[0], dimensions[1], 1));
 
  692   template <
typename Invocation>
 
  697                                      internal::detail::DispatcherBaseTryExecuteFunctor(),
 
  713   DispatcherBase(
const MyType&) = 
delete;
 
  714   void operator=(
const MyType&) = 
delete;
 
  718   template <
typename Invocation,
 
  719             typename InputRangeType,
 
  720             typename OutputRangeType,
 
  721             typename ThreadRangeType,
 
  722             typename DeviceAdapter>
 
  723   VTKM_CONT void InvokeTransportParameters(Invocation& invocation,
 
  724                                            const InputRangeType& inputRange,
 
  725                                            OutputRangeType&& outputRange,
 
  726                                            ThreadRangeType&& threadRange,
 
  727                                            DeviceAdapter device)
 const 
  742     using ParameterInterfaceType = 
typename Invocation::ParameterInterface;
 
  743     ParameterInterfaceType& parameters = invocation.Parameters;
 
  745     using TransportFunctorType =
 
  746       detail::DispatcherBaseTransportFunctor<
typename Invocation::ControlInterface,
 
  747                                              typename Invocation::InputDomainType,
 
  749     using ExecObjectParameters =
 
  750       typename ParameterInterfaceType::template StaticTransformType<TransportFunctorType>::type;
 
  752     ExecObjectParameters execObjectParameters = parameters.StaticTransformCont(
 
  753       TransportFunctorType(invocation.GetInputDomain(), inputRange, outputRange, token));
 
  756     typename ScatterType::OutputToInputMapType outputToInputMap =
 
  757       this->Scatter.GetOutputToInputMap(inputRange);
 
  758     typename ScatterType::VisitArrayType visitArray = this->Scatter.GetVisitArray(inputRange);
 
  761     typename MaskType::ThreadToOutputMapType threadToOutputMap =
 
  762       this->Mask.GetThreadToOutputMap(inputRange);
 
  766     vtkm::internal::Invocation<ExecObjectParameters,
 
  767                                typename Invocation::ControlInterface,
 
  768                                typename Invocation::ExecutionInterface,
 
  769                                Invocation::InputDomainIndex,
 
  770                                decltype(outputToInputMap.PrepareForInput(device, token)),
 
  771                                decltype(visitArray.PrepareForInput(device, token)),
 
  772                                decltype(threadToOutputMap.PrepareForInput(device, token)),
 
  774       changedInvocation(execObjectParameters,
 
  775                         outputToInputMap.PrepareForInput(device, token),
 
  776                         visitArray.PrepareForInput(device, token),
 
  777                         threadToOutputMap.PrepareForInput(device, token));
 
  779     this->InvokeSchedule(changedInvocation, threadRange, device);
 
  782   template <
typename Invocation, 
typename RangeType, 
typename DeviceAdapter>
 
  783   VTKM_CONT void InvokeSchedule(
const Invocation& invocation, RangeType range, DeviceAdapter)
 const 
  795     auto task = TaskTypes::MakeTask(this->Worklet, invocation, range);
 
  796     Algorithm::ScheduleTask(task, range);
 
  803 #endif //vtk_m_worklet_internal_DispatcherBase_h