DPC++ Runtime
Runtime libraries for oneAPI DPC++
kernel_bundle.hpp
Go to the documentation of this file.
1 //==------- kernel_bundle.hpp - SYCL kernel_bundle and free functions ------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
11 #include <sycl/backend_types.hpp> // for backend, backend_return_t
12 #include <sycl/context.hpp> // for context
13 #include <sycl/detail/export.hpp> // for __SYCL_EXPORT
14 #include <sycl/detail/kernel_desc.hpp> // for get_spec_constant_symboli...
15 #include <sycl/detail/owner_less_base.hpp> // for OwnerLessBase
17 #include <sycl/detail/ur.hpp> // for cast
18 #include <sycl/device.hpp> // for device
19 #include <sycl/kernel.hpp> // for kernel, kernel_bundle
20 #include <sycl/kernel_bundle_enums.hpp> // for bundle_state
21 #include <sycl/property_list.hpp> // for property_list
22 #include <ur_api.h> // for ur_native_handle_t
23 
25 #include <sycl/ext/oneapi/properties/properties.hpp> // PropertyT
26 #include <sycl/ext/oneapi/properties/property.hpp> // build_options
28 
29 #include <array> // for array
30 #include <cstddef> // for std::byte
31 #include <cstring> // for size_t, memcpy
32 #include <functional> // for function
33 #include <iterator> // for distance
34 #include <memory> // for shared_ptr, operator==, hash
35 #include <string> // for string
36 #include <type_traits> // for enable_if_t, remove_refer...
37 #include <utility> // for move
38 #include <variant> // for hash
39 #include <vector> // for vector
40 
41 namespace sycl {
42 inline namespace _V1 {
43 // Forward declaration
44 template <backend Backend> class backend_traits;
45 template <backend Backend, bundle_state State>
46 auto get_native(const kernel_bundle<State> &Obj)
47  -> backend_return_t<Backend, kernel_bundle<State>>;
48 
49 namespace detail {
50 class kernel_id_impl;
51 class kernel_impl;
52 } // namespace detail
53 
54 template <typename KernelName> kernel_id get_kernel_id();
55 
56 namespace ext::oneapi::experimental {
57 template <auto *Func>
58 std::enable_if_t<is_kernel_v<Func>, kernel_id> get_kernel_id();
59 } // namespace ext::oneapi::experimental
60 
64 class __SYCL_EXPORT kernel_id : public detail::OwnerLessBase<kernel_id> {
65 public:
66  kernel_id() = delete;
67 
69  const char *get_name() const noexcept;
70 
71  bool operator==(const kernel_id &RHS) const { return impl == RHS.impl; }
72 
73  bool operator!=(const kernel_id &RHS) const { return !(*this == RHS); }
74 
75 private:
76  kernel_id(const char *Name);
77 
78  kernel_id(const std::shared_ptr<detail::kernel_id_impl> &Impl)
79  : impl(std::move(Impl)) {}
80 
81  std::shared_ptr<detail::kernel_id_impl> impl;
82 
83  template <class Obj>
84  friend const decltype(Obj::impl) &
85  detail::getSyclObjImpl(const Obj &SyclObject);
86 
87  template <class T>
88  friend T detail::createSyclObjFromImpl(decltype(T::impl) ImplObj);
89 };
90 
91 namespace detail {
92 class device_image_impl;
93 using DeviceImageImplPtr = std::shared_ptr<device_image_impl>;
94 
95 // The class is used as a base for device_image for "untemplating" public
96 // methods.
97 class __SYCL_EXPORT device_image_plain {
98 public:
100  : impl(std::move(Impl)) {}
101 
102  bool operator==(const device_image_plain &RHS) const {
103  return impl == RHS.impl;
104  }
105 
106  bool operator!=(const device_image_plain &RHS) const {
107  return !(*this == RHS);
108  }
109 
110  bool has_kernel(const kernel_id &KernelID) const noexcept;
111 
112  bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept;
113 
114  ur_native_handle_t getNative() const;
115 
116 protected:
118 
119  template <class Obj>
120  friend const decltype(Obj::impl) &
121  detail::getSyclObjImpl(const Obj &SyclObject);
122 
123  template <class T>
124  friend T detail::createSyclObjFromImpl(decltype(T::impl) ImplObj);
125 };
126 } // namespace detail
127 
129 template <sycl::bundle_state State>
131  public detail::OwnerLessBase<device_image<State>> {
132 public:
133  device_image() = delete;
134 
137  bool has_kernel(const kernel_id &KernelID) const noexcept {
138  return device_image_plain::has_kernel(KernelID);
139  }
140 
143  bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept {
144  return device_image_plain::has_kernel(KernelID, Dev);
145  }
146 
147 private:
149  : device_image_plain(std::move(Impl)) {}
150 
151  template <class Obj>
152  friend const decltype(Obj::impl) &
153  detail::getSyclObjImpl(const Obj &SyclObject);
154 
155  template <class T>
156  friend T detail::createSyclObjFromImpl(decltype(T::impl) ImplObj);
157 };
158 
159 namespace detail {
160 class kernel_bundle_impl;
161 using KernelBundleImplPtr = std::shared_ptr<detail::kernel_bundle_impl>;
162 
163 // The class is used as a base for kernel_bundle to "untemplate" it's methods
164 class __SYCL_EXPORT kernel_bundle_plain {
165 public:
167  : impl(std::move(Impl)) {}
168 
169  bool operator==(const kernel_bundle_plain &RHS) const {
170  return impl == RHS.impl;
171  }
172 
173  bool operator!=(const kernel_bundle_plain &RHS) const {
174  return !(*this == RHS);
175  }
176 
177  bool empty() const noexcept;
178 
179  backend get_backend() const noexcept;
180 
181  context get_context() const noexcept;
182 
183  std::vector<device> get_devices() const noexcept;
184 
185  bool has_kernel(const kernel_id &KernelID) const noexcept;
186 
187  bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept;
188 
189  std::vector<kernel_id> get_kernel_ids() const;
190 
191  bool contains_specialization_constants() const noexcept;
192 
193  bool native_specialization_constant() const noexcept;
194 
195  bool ext_oneapi_has_kernel(const std::string &name) {
196  return ext_oneapi_has_kernel(detail::string_view{name});
197  }
198 
199  kernel ext_oneapi_get_kernel(const std::string &name) {
200  return ext_oneapi_get_kernel(detail::string_view{name});
201  }
202 
203 protected:
204  // \returns a kernel object which represents the kernel identified by
205  // kernel_id passed
206  kernel get_kernel(const kernel_id &KernelID) const;
207 
208  // \returns an iterator to the first device image kernel_bundle contains
209  const device_image_plain *begin() const;
210 
211  // \returns an iterator to the last device image kernel_bundle contains
212  const device_image_plain *end() const;
213 
214  bool has_specialization_constant_impl(const char *SpecName) const noexcept;
215 
216  void set_specialization_constant_impl(const char *SpecName, void *Value,
217  size_t Size) noexcept;
218 
219  void get_specialization_constant_impl(const char *SpecName,
220  void *Value) const noexcept;
221 
222  // \returns a bool value which indicates if specialization constant was set to
223  // a value different from default value.
224  bool is_specialization_constant_set(const char *SpecName) const noexcept;
225 
227 
228 private:
229  bool ext_oneapi_has_kernel(detail::string_view name);
230  kernel ext_oneapi_get_kernel(detail::string_view name);
231 };
232 
233 } // namespace detail
234 
239 template <bundle_state State>
241  public detail::OwnerLessBase<kernel_bundle<State>> {
242 public:
244 
245  kernel_bundle() = delete;
246 
248  template <
249  bundle_state _State = State,
250  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
251  bool empty() const noexcept {
252  return kernel_bundle_plain::empty();
253  }
254 
257  return kernel_bundle_plain::get_backend();
258  }
259 
262  return kernel_bundle_plain::get_context();
263  }
264 
266  std::vector<device> get_devices() const noexcept {
267  return kernel_bundle_plain::get_devices();
268  }
269 
272  template <
273  bundle_state _State = State,
274  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
275  bool has_kernel(const kernel_id &KernelID) const noexcept {
276  return kernel_bundle_plain::has_kernel(KernelID);
277  }
278 
282  template <
283  bundle_state _State = State,
284  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
285  bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept {
286  return kernel_bundle_plain::has_kernel(KernelID, Dev);
287  }
288 
291  template <
292  typename KernelName, bundle_state _State = State,
293  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
294  bool has_kernel() const noexcept {
295  return has_kernel(get_kernel_id<KernelName>());
296  }
297 
300  template <
301  typename KernelName, bundle_state _State = State,
302  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
303  bool has_kernel(const device &Dev) const noexcept {
304  return has_kernel(get_kernel_id<KernelName>(), Dev);
305  }
306 
308  template <
309  bundle_state _State = State,
310  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
311  std::vector<kernel_id> get_kernel_ids() const {
313  }
314 
317  template <
318  bundle_state _State = State,
319  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
321  return kernel_bundle_plain::contains_specialization_constants();
322  }
323 
326  template <
327  bundle_state _State = State,
328  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
330  return kernel_bundle_plain::native_specialization_constant();
331  }
332 
335  template <bundle_state _State = State,
336  typename = std::enable_if_t<_State == bundle_state::executable>>
337  kernel get_kernel(const kernel_id &KernelID) const {
339  }
340 
343  template <typename KernelName, bundle_state _State = State,
344  typename = std::enable_if_t<_State == bundle_state::executable>>
345  kernel get_kernel() const {
346  return detail::kernel_bundle_plain::get_kernel(get_kernel_id<KernelName>());
347  }
348 
351  template <
352  auto &SpecName, bundle_state _State = State,
353  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
355  const char *SpecSymName = detail::get_spec_constant_symbolic_ID<SpecName>();
356  return has_specialization_constant_impl(SpecSymName);
357  }
358 
362  template <auto &SpecName, bundle_state _State = State,
363  typename = std::enable_if_t<_State == bundle_state::input>>
365  typename std::remove_reference_t<decltype(SpecName)>::value_type Value) {
366  const char *SpecSymName = detail::get_spec_constant_symbolic_ID<SpecName>();
367  set_specialization_constant_impl(SpecSymName, &Value,
368  sizeof(decltype(Value)));
369  }
370 
373  template <
374  auto &SpecName, bundle_state _State = State,
375  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
376  typename std::remove_reference_t<decltype(SpecName)>::value_type
378  using SCType =
379  typename std::remove_reference_t<decltype(SpecName)>::value_type;
380 
381  const char *SpecSymName = detail::get_spec_constant_symbolic_ID<SpecName>();
382  SCType Res{SpecName.getDefaultValue()};
383  if (!is_specialization_constant_set(SpecSymName))
384  return Res;
385 
386  std::array<char, sizeof(SCType)> RetValue;
387  get_specialization_constant_impl(SpecSymName, RetValue.data());
388  std::memcpy(&Res, RetValue.data(), sizeof(SCType));
389 
390  return Res;
391  }
392 
394  template <
395  bundle_state _State = State,
396  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
398  return reinterpret_cast<device_image_iterator>(
399  kernel_bundle_plain::begin());
400  }
401 
403  template <
404  bundle_state _State = State,
405  typename = std::enable_if_t<_State != bundle_state::ext_oneapi_source>>
407  return reinterpret_cast<device_image_iterator>(kernel_bundle_plain::end());
408  }
409 
411  // ext_oneapi_has_kernel
412  // only true if created from source and has this kernel
414  template <bundle_state _State = State,
415  typename = std::enable_if_t<_State == bundle_state::executable>>
416  bool ext_oneapi_has_kernel(const std::string &name) {
418  }
419 
420  // For free functions.
421  template <auto *Func>
422  std::enable_if_t<ext::oneapi::experimental::is_kernel_v<Func>, bool>
424  return has_kernel(ext::oneapi::experimental::get_kernel_id<Func>());
425  }
426 
427  template <auto *Func>
428  std::enable_if_t<ext::oneapi::experimental::is_kernel_v<Func>, bool>
430  return has_kernel(ext::oneapi::experimental::get_kernel_id<Func>(), dev);
431  }
432 
433  template <auto *Func, bundle_state _State = State,
434  typename = std::enable_if_t<_State == bundle_state::executable>>
435  std::enable_if_t<ext::oneapi::experimental::is_kernel_v<Func>, kernel>
438  ext::oneapi::experimental::get_kernel_id<Func>());
439  }
440 
442  // ext_oneapi_get_kernel
443  // kernel_bundle must be created from source, throws if not present
445  template <bundle_state _State = State,
446  typename = std::enable_if_t<_State == bundle_state::executable>>
447  kernel ext_oneapi_get_kernel(const std::string &name) {
449  }
450 
451 private:
453  : kernel_bundle_plain(std::move(Impl)) {}
454 
455  template <class Obj>
456  friend const decltype(Obj::impl) &
457  detail::getSyclObjImpl(const Obj &SyclObject);
458 
459  template <class T>
460  friend T detail::createSyclObjFromImpl(decltype(T::impl) ImplObj);
461 
462  template <backend Backend, bundle_state StateB>
463  friend auto get_native(const kernel_bundle<StateB> &Obj)
465 
466  template <backend Backend>
468  // NOTE: implementation assumes that the return type is a
469  // derivative of std::vector.
471  ReturnValue.reserve(std::distance(begin(), end()));
472 
473  for (const device_image<State> &DevImg : *this) {
474  ReturnValue.push_back(
475  detail::ur::cast<typename decltype(ReturnValue)::value_type>(
476  DevImg.getNative()));
477  }
478 
479  return ReturnValue;
480  }
481 };
482 template <bundle_state State>
484 
486 // get_kernel_id API
488 
489 namespace detail {
490 // Internal non-template versions of get_kernel_id API which is used by public
491 // onces
492 __SYCL_EXPORT kernel_id get_kernel_id_impl(string_view KernelName);
493 } // namespace detail
494 
496 template <typename KernelName> kernel_id get_kernel_id() {
497  // FIXME: This must fail at link-time if KernelName not in any available
498  // translation units.
499  using KI = sycl::detail::KernelInfo<KernelName>;
500  return detail::get_kernel_id_impl(detail::string_view{KI::getName()});
501 }
502 
504 __SYCL_EXPORT std::vector<kernel_id> get_kernel_ids();
505 
507 // get_kernel_bundle API
509 
510 namespace detail {
511 
512 // Internal non-template versions of get_kernel_bundle API which is used by
513 // public onces
514 __SYCL_EXPORT detail::KernelBundleImplPtr
515 get_kernel_bundle_impl(const context &Ctx, const std::vector<device> &Devs,
516  bundle_state State);
517 
518 __SYCL_EXPORT const std::vector<device>
519 removeDuplicateDevices(const std::vector<device> &Devs);
520 
521 } // namespace detail
522 
527 template <bundle_state State>
529  const std::vector<device> &Devs) {
530  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
531 
533  detail::get_kernel_bundle_impl(Ctx, UniqueDevices, State);
534 
535  return detail::createSyclObjFromImpl<kernel_bundle<State>>(Impl);
536 }
537 
538 template <bundle_state State>
540  return get_kernel_bundle<State>(Ctx, Ctx.get_devices());
541 }
542 
543 namespace detail {
544 
545 // Internal non-template versions of get_kernel_bundle API which is used by
546 // public onces
547 __SYCL_EXPORT detail::KernelBundleImplPtr
548 get_kernel_bundle_impl(const context &Ctx, const std::vector<device> &Devs,
549  const std::vector<kernel_id> &KernelIDs,
550  bundle_state State);
551 } // namespace detail
552 
561 template <bundle_state State>
562 kernel_bundle<State>
563 get_kernel_bundle(const context &Ctx, const std::vector<device> &Devs,
564  const std::vector<kernel_id> &KernelIDs) {
565  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
566 
568  detail::get_kernel_bundle_impl(Ctx, UniqueDevices, KernelIDs, State);
569  return detail::createSyclObjFromImpl<kernel_bundle<State>>(Impl);
570 }
571 
572 template <bundle_state State>
573 kernel_bundle<State>
574 get_kernel_bundle(const context &Ctx, const std::vector<kernel_id> &KernelIDs) {
575  return get_kernel_bundle<State>(Ctx, Ctx.get_devices(), KernelIDs);
576 }
577 
578 template <typename KernelName, bundle_state State>
580  return get_kernel_bundle<State>(Ctx, Ctx.get_devices(),
581  {get_kernel_id<KernelName>()});
582 }
583 
584 template <typename KernelName, bundle_state State>
586  const std::vector<device> &Devs) {
587  return get_kernel_bundle<State>(Ctx, Devs, {get_kernel_id<KernelName>()});
588 }
589 
590 // For free functions.
591 namespace ext::oneapi::experimental {
592 template <auto *Func, bundle_state State>
593 std::enable_if_t<is_kernel_v<Func>, kernel_bundle<State>>
594 get_kernel_bundle(const context &Ctx, const std::vector<device> &Devs) {
595  return get_kernel_bundle<State>(Ctx, Devs, {get_kernel_id<Func>()});
596 }
597 
598 template <auto *Func, bundle_state State>
599 std::enable_if_t<is_kernel_v<Func>, kernel_bundle<State>>
601  return get_kernel_bundle<State>(Ctx, Ctx.get_devices(),
602  {get_kernel_id<Func>()});
603 }
604 } // namespace ext::oneapi::experimental
605 
606 namespace detail {
607 
608 // Stable selector function type for passing thru library boundaries
610  std::function<bool(const detail::DeviceImageImplPtr &DevImgImpl)>;
611 
612 // Internal non-template versions of get_kernel_bundle API which is used by
613 // public onces
614 __SYCL_EXPORT detail::KernelBundleImplPtr
615 get_kernel_bundle_impl(const context &Ctx, const std::vector<device> &Devs,
616  bundle_state State, const DevImgSelectorImpl &Selector);
617 
618 // Internal non-template versions of get_empty_interop_kernel_bundle API which
619 // is used by public onces
620 __SYCL_EXPORT detail::KernelBundleImplPtr
622  const std::vector<device> &Devs);
623 
626 template <bundle_state State>
630  return detail::createSyclObjFromImpl<sycl::kernel_bundle<State>>(Impl);
631 }
632 } // namespace detail
633 
636 template <bundle_state State, typename SelectorT>
638  const std::vector<device> &Devs,
639  SelectorT Selector) {
640  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
641 
642  detail::DevImgSelectorImpl SelectorWrapper =
643  [Selector](const detail::DeviceImageImplPtr &DevImg) {
644  return Selector(
646  };
647 
649  Ctx, UniqueDevices, State, SelectorWrapper);
650 
651  return detail::createSyclObjFromImpl<sycl::kernel_bundle<State>>(Impl);
652 }
653 
654 template <bundle_state State, typename SelectorT>
655 kernel_bundle<State> get_kernel_bundle(const context &Ctx, SelectorT Selector) {
656  return get_kernel_bundle<State>(Ctx, Ctx.get_devices(), Selector);
657 }
658 
660 // has_kernel_bundle API
662 
663 namespace detail {
664 
665 __SYCL_EXPORT bool has_kernel_bundle_impl(const context &Ctx,
666  const std::vector<device> &Devs,
667  bundle_state State);
668 
669 __SYCL_EXPORT bool
670 has_kernel_bundle_impl(const context &Ctx, const std::vector<device> &Devs,
671  const std::vector<kernel_id> &kernelIds,
672  bundle_state State);
673 } // namespace detail
674 
685 template <bundle_state State>
686 bool has_kernel_bundle(const context &Ctx, const std::vector<device> &Devs) {
687  return detail::has_kernel_bundle_impl(Ctx, Devs, State);
688 }
689 
690 template <bundle_state State>
691 bool has_kernel_bundle(const context &Ctx, const std::vector<device> &Devs,
692  const std::vector<kernel_id> &KernelIDs) {
693  return detail::has_kernel_bundle_impl(Ctx, Devs, KernelIDs, State);
694 }
695 
696 template <bundle_state State> bool has_kernel_bundle(const context &Ctx) {
697  return has_kernel_bundle<State>(Ctx, Ctx.get_devices());
698 }
699 
700 template <bundle_state State>
701 bool has_kernel_bundle(const context &Ctx,
702  const std::vector<kernel_id> &KernelIDs) {
703  return has_kernel_bundle<State>(Ctx, Ctx.get_devices(), KernelIDs);
704 }
705 
706 template <typename KernelName, bundle_state State>
707 bool has_kernel_bundle(const context &Ctx) {
708  return has_kernel_bundle<State>(Ctx, {get_kernel_id<KernelName>()});
709 }
710 
711 template <typename KernelName, bundle_state State>
712 bool has_kernel_bundle(const context &Ctx, const std::vector<device> &Devs) {
713  return has_kernel_bundle<State>(Ctx, Devs, {get_kernel_id<KernelName>()});
714 }
715 
716 // For free functions.
717 namespace ext::oneapi::experimental {
718 template <auto *Func, bundle_state State>
719 std::enable_if_t<is_kernel_v<Func>, bool>
721  return has_kernel_bundle<State>(Ctx, {get_kernel_id<Func>()});
722 }
723 
724 template <auto *Func, bundle_state State>
725 std::enable_if_t<is_kernel_v<Func>, bool>
726 has_kernel_bundle(const context &Ctx, const std::vector<device> &Devs) {
727  return has_kernel_bundle<State>(Ctx, Devs, {get_kernel_id<Func>()});
728 }
729 } // namespace ext::oneapi::experimental
730 
732 // is_compatible API
734 
737 __SYCL_EXPORT bool is_compatible(const std::vector<kernel_id> &KernelIDs,
738  const device &Dev);
739 
740 template <typename KernelName> bool is_compatible(const device &Dev) {
741  return is_compatible({get_kernel_id<KernelName>()}, Dev);
742 }
743 
744 // For free functions.
745 namespace ext::oneapi::experimental {
746 template <auto *Func>
747 std::enable_if_t<is_kernel_v<Func>, bool> is_compatible(const device &Dev) {
748  return is_compatible({get_kernel_id<Func>()}, Dev);
749 }
750 } // namespace ext::oneapi::experimental
751 
753 // join API
755 
756 namespace detail {
757 
758 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
759 join_impl(const std::vector<detail::KernelBundleImplPtr> &Bundles,
760  bundle_state State);
761 } // namespace detail
762 
765 template <sycl::bundle_state State>
767 join(const std::vector<sycl::kernel_bundle<State>> &Bundles) {
768  // Convert kernel_bundle<State> to impls to abstract template parameter away
769  std::vector<detail::KernelBundleImplPtr> KernelBundleImpls;
770  KernelBundleImpls.reserve(Bundles.size());
771  for (const sycl::kernel_bundle<State> &Bundle : Bundles)
772  KernelBundleImpls.push_back(detail::getSyclObjImpl(Bundle));
773 
774  std::shared_ptr<detail::kernel_bundle_impl> Impl =
775  detail::join_impl(KernelBundleImpls, State);
776  return detail::createSyclObjFromImpl<kernel_bundle<State>>(Impl);
777 }
778 
780 // compile API
782 
783 namespace detail {
784 
785 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
786 compile_impl(const kernel_bundle<bundle_state::input> &InputBundle,
787  const std::vector<device> &Devs, const property_list &PropList);
788 }
789 
794 inline kernel_bundle<bundle_state::object>
796  const std::vector<device> &Devs, const property_list &PropList = {}) {
797  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
798 
800  detail::compile_impl(InputBundle, UniqueDevices, PropList);
802  kernel_bundle<sycl::bundle_state::object>>(Impl);
803 }
804 
805 inline kernel_bundle<bundle_state::object>
807  const property_list &PropList = {}) {
808  return compile(InputBundle, InputBundle.get_devices(), PropList);
809 }
810 
812 // link API
814 
815 namespace detail {
816 __SYCL_EXPORT std::vector<sycl::device> find_device_intersection(
817  const std::vector<kernel_bundle<bundle_state::object>> &ObjectBundles);
818 
819 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
820 link_impl(const std::vector<kernel_bundle<bundle_state::object>> &ObjectBundles,
821  const std::vector<device> &Devs, const property_list &PropList);
822 } // namespace detail
823 
829 inline kernel_bundle<bundle_state::executable>
830 link(const std::vector<kernel_bundle<bundle_state::object>> &ObjectBundles,
831  const std::vector<device> &Devs, const property_list &PropList = {}) {
832  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
833 
835  detail::link_impl(ObjectBundles, UniqueDevices, PropList);
837  kernel_bundle<sycl::bundle_state::executable>>(Impl);
838 }
839 
840 inline kernel_bundle<bundle_state::executable>
842  const property_list &PropList = {}) {
843  return link(std::vector<kernel_bundle<bundle_state::object>>{ObjectBundle},
844  ObjectBundle.get_devices(), PropList);
845 }
846 
847 inline kernel_bundle<bundle_state::executable>
848 link(const std::vector<kernel_bundle<bundle_state::object>> &ObjectBundles,
849  const property_list &PropList = {}) {
850  std::vector<sycl::device> IntersectDevices =
851  find_device_intersection(ObjectBundles);
852  return link(ObjectBundles, IntersectDevices, PropList);
853 }
854 
855 inline kernel_bundle<bundle_state::executable>
857  const std::vector<device> &Devs, const property_list &PropList = {}) {
858  return link(std::vector<kernel_bundle<bundle_state::object>>{ObjectBundle},
859  Devs, PropList);
860 }
861 
863 // build API
865 
866 namespace detail {
867 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
868 build_impl(const kernel_bundle<bundle_state::input> &InputBundle,
869  const std::vector<device> &Devs, const property_list &PropList);
870 }
871 
876 inline kernel_bundle<bundle_state::executable>
878  const std::vector<device> &Devs, const property_list &PropList = {}) {
879  std::vector<device> UniqueDevices = detail::removeDuplicateDevices(Devs);
880 
882  detail::build_impl(InputBundle, UniqueDevices, PropList);
884  kernel_bundle<sycl::bundle_state::executable>>(Impl);
885 }
886 
887 inline kernel_bundle<bundle_state::executable>
889  const property_list &PropList = {}) {
890  return build(InputBundle, InputBundle.get_devices(), PropList);
891 }
892 
893 namespace ext::oneapi::experimental {
894 
895 namespace detail {
896 struct create_bundle_from_source_props;
897 struct build_source_bundle_props;
898 } // namespace detail
899 
901 // PropertyT syclex::include_files
904  : detail::run_time_property_key<detail::PropKind::IncludeFiles> {
906  include_files(const std::string &name, const std::string &content) {
907  record.emplace_back(std::make_pair(name, content));
908  }
909  void add(const std::string &name, const std::string &content) {
910  record.emplace_back(std::make_pair(name, content));
911  }
912  std::vector<std::pair<std::string, std::string>> record;
913 };
915 
916 template <>
918  detail::create_bundle_from_source_props>
919  : std::true_type {};
920 
922 // PropertyT syclex::build_options
925  : detail::run_time_property_key<detail::PropKind::BuildOptions> {
926  std::vector<std::string> opts;
927  build_options(const std::string &optsArg) : opts{optsArg} {}
928  build_options(const std::vector<std::string> &optsArg) : opts(optsArg) {}
929 };
931 
932 template <>
933 struct is_property_key_of<build_options_key, detail::build_source_bundle_props>
934  : std::true_type {};
935 
937 // PropertyT syclex::save_log
939 struct save_log : detail::run_time_property_key<detail::PropKind::BuildLog> {
940  std::string *log;
941  save_log(std::string *logArg) : log(logArg) {}
942 };
944 
945 template <>
946 struct is_property_key_of<save_log_key, detail::build_source_bundle_props>
947  : std::true_type {};
948 
950 // PropertyT syclex::registered_kernel_names
953  : detail::run_time_property_key<detail::PropKind::RegisteredKernelNames> {
954  std::vector<std::string> kernel_names;
956  registered_kernel_names(const std::string &knArg) : kernel_names{knArg} {}
957  registered_kernel_names(const std::vector<std::string> &knsArg)
958  : kernel_names(knsArg) {}
959  void add(const std::string &name) { kernel_names.push_back(name); }
960 };
962 
963 template <>
965  detail::build_source_bundle_props> : std::true_type {
966 };
967 
968 namespace detail {
969 // forward decls
970 __SYCL_EXPORT bool is_source_kernel_bundle_supported(backend BE,
971  source_language Language);
972 
975  const context &SyclContext, source_language Language,
976  sycl::detail::string_view Source,
977  std::vector<std::pair<sycl::detail::string_view, sycl::detail::string_view>>
978  IncludePairsVec);
979 
982  const context &SyclContext, source_language Language,
983  const std::string &Source,
984  std::vector<std::pair<std::string, std::string>> IncludePairsVec) {
985  size_t n = IncludePairsVec.size();
986  std::vector<std::pair<sycl::detail::string_view, sycl::detail::string_view>>
987  PairVec;
988  PairVec.reserve(n);
989  for (auto &Pair : IncludePairsVec)
990  PairVec.push_back({sycl::detail::string_view{Pair.first},
991  sycl::detail::string_view{Pair.second}});
992 
994  SyclContext, Language, sycl::detail::string_view{Source}, PairVec);
995 }
996 
997 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
1000  const context &SyclContext, source_language Language,
1001  const std::vector<std::byte> &Bytes,
1002  std::vector<std::pair<sycl::detail::string_view, sycl::detail::string_view>>
1003  IncludePairsVec);
1004 
1007  const context &SyclContext, source_language Language,
1008  const std::vector<std::byte> &Bytes,
1009  std::vector<std::pair<std::string, std::string>> IncludePairsVec) {
1010  size_t n = IncludePairsVec.size();
1011  std::vector<std::pair<sycl::detail::string_view, sycl::detail::string_view>>
1012  PairVec;
1013  PairVec.reserve(n);
1014  for (auto &Pair : IncludePairsVec)
1015  PairVec.push_back({sycl::detail::string_view{Pair.first},
1016  sycl::detail::string_view{Pair.second}});
1017 
1018  return make_kernel_bundle_from_source(SyclContext, Language, Bytes, PairVec);
1019 }
1020 #endif
1021 
1024  const std::vector<device> &Devices,
1025  const std::vector<sycl::detail::string_view> &BuildOptions,
1026  sycl::detail::string *LogPtr,
1027  const std::vector<sycl::detail::string_view> &RegisteredKernelNames);
1028 
1031  const std::vector<device> &Devices,
1032  const std::vector<std::string> &BuildOptions,
1033  std::string *LogPtr,
1034  const std::vector<std::string> &RegisteredKernelNames) {
1035  std::vector<sycl::detail::string_view> Options;
1036  for (const std::string &opt : BuildOptions)
1037  Options.push_back(sycl::detail::string_view{opt});
1038 
1039  std::vector<sycl::detail::string_view> KernelNames;
1040  for (const std::string &name : RegisteredKernelNames)
1041  KernelNames.push_back(sycl::detail::string_view{name});
1042 
1043  if (LogPtr) {
1044  sycl::detail::string Log;
1045  auto result =
1046  build_from_source(SourceKB, Devices, Options, &Log, KernelNames);
1047  *LogPtr = Log.c_str();
1048  return result;
1049  }
1050  return build_from_source(SourceKB, Devices, Options, nullptr, KernelNames);
1051 }
1052 } // namespace detail
1053 
1055 // syclex::create_kernel_bundle_from_source
1057 template <
1058  typename PropertyListT = empty_properties_t,
1059  typename = std::enable_if_t<
1060  is_property_list_v<PropertyListT> &&
1061  detail::all_props_are_keys_of<detail::create_bundle_from_source_props,
1062  PropertyListT>::value>>
1064  const context &SyclContext, source_language Language,
1065  const std::string &Source, PropertyListT props = {}) {
1066  std::vector<std::pair<std::string, std::string>> IncludePairsVec;
1067  if constexpr (props.template has_property<include_files>()) {
1068  IncludePairsVec = props.template get_property<include_files>().record;
1069  }
1070 
1071  return detail::make_kernel_bundle_from_source(SyclContext, Language, Source,
1072  IncludePairsVec);
1073 }
1074 
1075 #if (!defined(_HAS_STD_BYTE) || _HAS_STD_BYTE != 0)
1076 template <
1077  typename PropertyListT = empty_properties_t,
1078  typename = std::enable_if_t<
1079  is_property_list_v<PropertyListT> &&
1080  detail::all_props_are_keys_of<detail::create_bundle_from_source_props,
1081  PropertyListT>::value>>
1083  const context &SyclContext, source_language Language,
1084  const std::vector<std::byte> &Bytes, PropertyListT props = {}) {
1085  std::vector<std::pair<std::string, std::string>> IncludePairsVec;
1086  if constexpr (props.template has_property<include_files>()) {
1087  IncludePairsVec = props.template get_property<include_files>().record;
1088  }
1089 
1090  return detail::make_kernel_bundle_from_source(SyclContext, Language, Bytes,
1091  IncludePairsVec);
1092 }
1093 #endif
1094 
1096 // syclex::build(source_kb) => exe_kb
1098 
1099 template <typename PropertyListT = empty_properties_t,
1100  typename = std::enable_if_t<
1101  is_property_list_v<PropertyListT> &&
1102  detail::all_props_are_keys_of<detail::build_source_bundle_props,
1103  PropertyListT>::value>>
1104 
1107  const std::vector<device> &Devices, PropertyListT props = {}) {
1108  std::vector<std::string> BuildOptionsVec;
1109  std::string *LogPtr = nullptr;
1110  std::vector<std::string> RegisteredKernelNamesVec;
1111  if constexpr (props.template has_property<build_options>()) {
1112  BuildOptionsVec = props.template get_property<build_options>().opts;
1113  }
1114  if constexpr (props.template has_property<save_log>()) {
1115  LogPtr = props.template get_property<save_log>().log;
1116  }
1117  if constexpr (props.template has_property<registered_kernel_names>()) {
1118  RegisteredKernelNamesVec =
1119  props.template get_property<registered_kernel_names>().kernel_names;
1120  }
1121  return detail::build_from_source(SourceKB, Devices, BuildOptionsVec, LogPtr,
1122  RegisteredKernelNamesVec);
1123 }
1124 
1125 template <typename PropertyListT = empty_properties_t,
1126  typename = std::enable_if_t<
1127  is_property_list_v<PropertyListT> &&
1128  detail::all_props_are_keys_of<detail::build_source_bundle_props,
1129  PropertyListT>::value>>
1130 kernel_bundle<bundle_state::executable>
1132  PropertyListT props = {}) {
1133  return build<PropertyListT>(SourceKB, SourceKB.get_devices(), props);
1134 }
1135 
1136 } // namespace ext::oneapi::experimental
1137 
1138 } // namespace _V1
1139 } // namespace sycl
1140 
1141 namespace std {
1142 template <> struct hash<sycl::kernel_id> {
1143  size_t operator()(const sycl::kernel_id &KernelID) const {
1144  return hash<std::shared_ptr<sycl::detail::kernel_id_impl>>()(
1145  sycl::detail::getSyclObjImpl(KernelID));
1146  }
1147 };
1148 
1149 template <sycl::bundle_state State> struct hash<sycl::device_image<State>> {
1150  size_t operator()(const sycl::device_image<State> &DeviceImage) const {
1151  return hash<std::shared_ptr<sycl::detail::device_image_impl>>()(
1152  sycl::detail::getSyclObjImpl(DeviceImage));
1153  }
1154 };
1155 
1156 template <sycl::bundle_state State> struct hash<sycl::kernel_bundle<State>> {
1157  size_t operator()(const sycl::kernel_bundle<State> &KernelBundle) const {
1158  return hash<std::shared_ptr<sycl::detail::kernel_bundle_impl>>()(
1159  sycl::detail::getSyclObjImpl(KernelBundle));
1160  }
1161 };
1162 } // namespace std
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
std::vector< device > get_devices() const
Gets devices associated with this SYCL context.
Definition: context.cpp:124
ur_native_handle_t getNative() const
bool operator==(const device_image_plain &RHS) const
device_image_plain(const detail::DeviceImageImplPtr &Impl)
bool operator!=(const device_image_plain &RHS) const
detail::DeviceImageImplPtr impl
bool operator!=(const kernel_bundle_plain &RHS) const
bool ext_oneapi_has_kernel(const std::string &name)
void get_specialization_constant_impl(const char *SpecName, void *Value) const noexcept
bool is_specialization_constant_set(const char *SpecName) const noexcept
bool has_specialization_constant_impl(const char *SpecName) const noexcept
detail::KernelBundleImplPtr impl
kernel_bundle_plain(const detail::KernelBundleImplPtr &Impl)
bool operator==(const kernel_bundle_plain &RHS) const
void set_specialization_constant_impl(const char *SpecName, void *Value, size_t Size) noexcept
kernel ext_oneapi_get_kernel(const std::string &name)
kernel get_kernel(const kernel_id &KernelID) const
Objects of the class represents an instance of an image in a specific state.
bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept
bool has_kernel(const kernel_id &KernelID) const noexcept
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
The kernel_bundle class represents collection of device images in a particular state.
bool ext_oneapi_has_kernel(const std::string &name)
std::vector< kernel_id > get_kernel_ids() const
bool contains_specialization_constants() const noexcept
bool has_kernel(const kernel_id &KernelID) const noexcept
bool has_specialization_constant() const noexcept
device_image_iterator begin() const
device_image_iterator end() const
kernel get_kernel(const kernel_id &KernelID) const
bool has_kernel(const device &Dev) const noexcept
kernel ext_oneapi_get_kernel(const std::string &name)
backend get_backend() const noexcept
std::enable_if_t< ext::oneapi::experimental::is_kernel_v< Func >, bool > ext_oneapi_has_kernel(const device &dev)
friend auto get_native(const kernel_bundle< StateB > &Obj) -> backend_return_t< Backend, kernel_bundle< StateB >>
std::vector< device > get_devices() const noexcept
bool has_kernel(const kernel_id &KernelID, const device &Dev) const noexcept
context get_context() const noexcept
std::enable_if_t< ext::oneapi::experimental::is_kernel_v< Func >, bool > ext_oneapi_has_kernel()
bool has_kernel() const noexcept
bool empty() const noexcept
bool native_specialization_constant() const noexcept
std::remove_reference_t< decltype(SpecName)>::value_type get_specialization_constant() const
std::enable_if_t< ext::oneapi::experimental::is_kernel_v< Func >, kernel > ext_oneapi_get_kernel()
void set_specialization_constant(typename std::remove_reference_t< decltype(SpecName)>::value_type Value)
Sets the value of the specialization constant whose address is SpecName for this bundle.
Objects of the class identify kernel is some kernel_bundle related APIs.
bool operator!=(const kernel_id &RHS) const
Provides an abstraction of a SYCL kernel.
Definition: kernel.hpp:71
Objects of the property_list class are containers for the SYCL properties.
To cast(std::vector< cl_event > value)
std::vector< sycl::device > find_device_intersection(const std::vector< kernel_bundle< bundle_state::object >> &ObjectBundles)
std::shared_ptr< detail::kernel_bundle_impl > build_impl(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList)
std::shared_ptr< device_image_impl > DeviceImageImplPtr
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
std::function< bool(const detail::DeviceImageImplPtr &DevImgImpl)> DevImgSelectorImpl
const std::vector< device > removeDuplicateDevices(const std::vector< device > &Devs)
detail::KernelBundleImplPtr get_kernel_bundle_impl(const context &Ctx, const std::vector< device > &Devs, bundle_state State)
T createSyclObjFromImpl(decltype(T::impl) ImplObj)
Definition: impl_utils.hpp:40
std::shared_ptr< detail::kernel_bundle_impl > compile_impl(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList)
std::shared_ptr< detail::kernel_bundle_impl > join_impl(const std::vector< detail::KernelBundleImplPtr > &Bundles, bundle_state State)
kernel_id get_kernel_id_impl(string_view KernelName)
std::shared_ptr< detail::kernel_bundle_impl > KernelBundleImplPtr
kernel_bundle< State > get_empty_interop_kernel_bundle(const context &Ctx)
make_kernel may need an empty interop kernel bundle.
bool has_kernel_bundle_impl(const context &Ctx, const std::vector< device > &Devs, bundle_state State)
detail::KernelBundleImplPtr get_empty_interop_kernel_bundle_impl(const context &Ctx, const std::vector< device > &Devs)
std::shared_ptr< detail::kernel_bundle_impl > link_impl(const std::vector< kernel_bundle< bundle_state::object >> &ObjectBundles, const std::vector< device > &Devs, const property_list &PropList)
kernel_bundle< bundle_state::ext_oneapi_source > make_kernel_bundle_from_source(const context &SyclContext, source_language Language, sycl::detail::string_view Source, std::vector< std::pair< sycl::detail::string_view, sycl::detail::string_view >> IncludePairsVec)
bool is_source_kernel_bundle_supported(backend BE, source_language Language)
kernel_bundle< bundle_state::executable > build_from_source(kernel_bundle< bundle_state::ext_oneapi_source > &SourceKB, const std::vector< device > &Devices, const std::vector< sycl::detail::string_view > &BuildOptions, sycl::detail::string *LogPtr, const std::vector< sycl::detail::string_view > &RegisteredKernelNames)
kernel_bundle< bundle_state::executable > build(kernel_bundle< bundle_state::ext_oneapi_source > &SourceKB, const std::vector< device > &Devices, PropertyListT props={})
std::enable_if_t< is_kernel_v< Func >, kernel_bundle< State > > get_kernel_bundle(const context &Ctx, const std::vector< device > &Devs)
kernel_bundle< bundle_state::ext_oneapi_source > create_kernel_bundle_from_source(const context &SyclContext, source_language Language, const std::string &Source, PropertyListT props={})
properties< std::tuple<> > empty_properties_t
Definition: properties.hpp:234
sycl::detail::kernel_bundle_impl kernel_bundle_impl
std::enable_if_t< is_kernel_v< Func >, bool > has_kernel_bundle(const context &Ctx)
std::enable_if_t< is_kernel_v< Func >, bool > is_compatible(const device &Dev)
std::enable_if_t< is_kernel_v< Func >, kernel_id > get_kernel_id()
kernel_bundle(kernel_bundle< State > &&) -> kernel_bundle< State >
sycl::kernel_bundle< State > join(const std::vector< sycl::kernel_bundle< State >> &Bundles)
kernel_bundle< bundle_state::executable > build(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList={})
kernel_id get_kernel_id()
kernel_bundle< bundle_state::object > compile(const kernel_bundle< bundle_state::input > &InputBundle, const std::vector< device > &Devs, const property_list &PropList={})
std::vector< kernel_id > get_kernel_ids()
bool is_compatible(const std::vector< kernel_id > &KernelIDs, const device &Dev)
bool has_kernel_bundle(const context &Ctx, const std::vector< device > &Devs)
kernel_bundle< State > get_kernel_bundle(const context &Ctx, const std::vector< device > &Devs)
A kernel bundle in state State which contains all of the kernels in the application which are compati...
auto get_native(const SyclObjectT &Obj) -> backend_return_t< BackendName, SyclObjectT >
Definition: backend.hpp:138
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:87
const void value_type
Definition: multi_ptr.hpp:457
kernel_bundle< bundle_state::executable > link(const std::vector< kernel_bundle< bundle_state::object >> &ObjectBundles, const std::vector< device > &Devs, const property_list &PropList={})
Definition: access.hpp:18
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
size_t operator()(const sycl::device_image< State > &DeviceImage) const
size_t operator()(const sycl::kernel_bundle< State > &KernelBundle) const
size_t operator()(const sycl::kernel_id &KernelID) const
build_options(const std::vector< std::string > &optsArg)
void add(const std::string &name, const std::string &content)
std::vector< std::pair< std::string, std::string > > record
include_files(const std::string &name, const std::string &content)
registered_kernel_names(const std::vector< std::string > &knsArg)
C++ utilities for Unified Runtime integration.