@@ -514,6 +514,98 @@ class __SYCL_EXPORT handler {
514
514
return {z, y, x};
515
515
}
516
516
517
+ /* The kernel passed to StoreLambda can take an id, an item or an nd_item as
518
+ * its argument. Since esimd plugin directly invokes the kernel (doesn’t use
519
+ * piKernelSetArg), the kernel argument type must be known to the plugin.
520
+ * However, passing kernel argument type to the plugin requires changing ABI
521
+ * in HostKernel class. To overcome this problem, helpers below wrap the
522
+ * “original” kernel with a functor that always takes an nd_item as argument.
523
+ * A functor is used instead of a lambda because extractArgsAndReqsFromLambda
524
+ * needs access to the “original” kernel and keeps references to its internal
525
+ * data, i.e. the kernel passed as argument cannot be local in scope. The
526
+ * functor itself is again encapsulated in a std::function since functor’s
527
+ * type is unknown to the plugin.
528
+ */
529
+
530
+ template <class KernelType , class NormalizedKernelType , int Dims>
531
+ KernelType *ResetHostKernelHelper (const KernelType &KernelFunc) {
532
+ NormalizedKernelType NormalizedKernel (KernelFunc);
533
+ auto NormalizedKernelFunc =
534
+ std::function<void (const sycl::nd_item<Dims> &)>(NormalizedKernel);
535
+ auto HostKernelPtr =
536
+ new detail::HostKernel<decltype (NormalizedKernelFunc),
537
+ sycl::nd_item<Dims>, Dims, KernelType>(
538
+ NormalizedKernelFunc);
539
+ MHostKernel.reset (HostKernelPtr);
540
+ return &HostKernelPtr->MKernel .template target <NormalizedKernelType>()
541
+ ->MKernelFunc ;
542
+ }
543
+
544
+ template <class KernelType , typename ArgT, int Dims>
545
+ typename std::enable_if<std::is_same<ArgT, sycl::id<Dims>>::value,
546
+ KernelType *>::type
547
+ ResetHostKernel (const KernelType &KernelFunc) {
548
+ struct NormalizedKernelType {
549
+ KernelType MKernelFunc;
550
+ NormalizedKernelType (const KernelType &KernelFunc)
551
+ : MKernelFunc(KernelFunc) {}
552
+ void operator ()(const nd_item<Dims> &Arg) {
553
+ MKernelFunc (Arg.get_global_id ());
554
+ }
555
+ };
556
+ return ResetHostKernelHelper<KernelType, struct NormalizedKernelType , Dims>(
557
+ KernelFunc);
558
+ }
559
+ template <class KernelType , typename ArgT, int Dims>
560
+ typename std::enable_if<std::is_same<ArgT, sycl::nd_item<Dims>>::value,
561
+ KernelType *>::type
562
+ ResetHostKernel (const KernelType &KernelFunc) {
563
+ struct NormalizedKernelType {
564
+ KernelType MKernelFunc;
565
+ NormalizedKernelType (const KernelType &KernelFunc)
566
+ : MKernelFunc(KernelFunc) {}
567
+ void operator ()(const nd_item<Dims> &Arg) { MKernelFunc (Arg); }
568
+ };
569
+ return ResetHostKernelHelper<KernelType, struct NormalizedKernelType , Dims>(
570
+ KernelFunc);
571
+ }
572
+
573
+ template <class KernelType , typename ArgT, int Dims>
574
+ typename std::enable_if<std::is_same<ArgT, sycl::item<Dims, false >>::value,
575
+ KernelType *>::type
576
+ ResetHostKernel (const KernelType &KernelFunc) {
577
+ struct NormalizedKernelType {
578
+ KernelType MKernelFunc;
579
+ NormalizedKernelType (const KernelType &KernelFunc)
580
+ : MKernelFunc(KernelFunc) {}
581
+ void operator ()(const nd_item<Dims> &Arg) {
582
+ sycl::item<Dims, false > Item = detail::Builder::createItem<Dims, false >(
583
+ Arg.get_global_range (), Arg.get_global_id ());
584
+ MKernelFunc (Item);
585
+ }
586
+ };
587
+ return ResetHostKernelHelper<KernelType, struct NormalizedKernelType , Dims>(
588
+ KernelFunc);
589
+ }
590
+
591
+ template <class KernelType , typename ArgT, int Dims>
592
+ typename std::enable_if<std::is_same<ArgT, sycl::item<Dims, true >>::value,
593
+ KernelType *>::type
594
+ ResetHostKernel (const KernelType &KernelFunc) {
595
+ struct NormalizedKernelType {
596
+ KernelType MKernelFunc;
597
+ NormalizedKernelType (const KernelType &KernelFunc)
598
+ : MKernelFunc(KernelFunc) {}
599
+ void operator ()(const nd_item<Dims> &Arg) {
600
+ sycl::item<Dims, true > Item = detail::Builder::createItem<Dims, true >(
601
+ Arg.get_global_range (), Arg.get_global_id (), Arg.get_offset ());
602
+ MKernelFunc (Item);
603
+ }
604
+ };
605
+ return ResetHostKernelHelper<KernelType, struct NormalizedKernelType , Dims>(
606
+ KernelFunc);
607
+ }
608
+
517
609
// / Stores lambda to the template-free object
518
610
// /
519
611
// / Also initializes kernel name, list of arguments and requirements using
@@ -530,18 +622,17 @@ class __SYCL_EXPORT handler {
530
622
" kernel_handler is not yet supported by host device." ,
531
623
PI_INVALID_OPERATION);
532
624
}
533
- MHostKernel.reset (
534
- new detail::HostKernel<KernelType, LambdaArgType, Dims, KernelName>(
535
- KernelFunc));
625
+ KernelType *KernelPtr =
626
+ ResetHostKernel<KernelType, LambdaArgType, Dims>(KernelFunc);
536
627
537
628
using KI = sycl::detail::KernelInfo<KernelName>;
538
629
// Empty name indicates that the compilation happens without integration
539
630
// header, so don't perform things that require it.
540
631
if (KI::getName () != nullptr && KI::getName ()[0 ] != ' \0 ' ) {
541
632
// TODO support ESIMD in no-integration-header case too.
542
633
MArgs.clear ();
543
- extractArgsAndReqsFromLambda (MHostKernel-> getPtr (), KI::getNumParams ( ),
544
- & KI::getParamDesc ( 0 ), KI::isESIMD ( ));
634
+ extractArgsAndReqsFromLambda (reinterpret_cast < char *>(KernelPtr ),
635
+ KI::getNumParams ( ), & KI::getParamDesc ( 0 ));
545
636
MKernelName = KI::getName ();
546
637
MOSModuleHandle = detail::OSUtil::getOSModuleHandle (KI::getName ());
547
638
} else {
0 commit comments