DPC++ Runtime
Runtime libraries for oneAPI DPC++
backend.hpp
Go to the documentation of this file.
1 //==---------------- backend.hpp - SYCL PI backends ------------------------==//
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 <CL/sycl/accessor.hpp>
13 #include <CL/sycl/buffer.hpp>
14 #include <CL/sycl/context.hpp>
16 #include <CL/sycl/feature_test.hpp>
17 #if SYCL_BACKEND_OPENCL
19 #endif
20 #if SYCL_EXT_ONEAPI_BACKEND_CUDA
21 #ifdef SYCL_EXT_ONEAPI_BACKEND_CUDA_EXPERIMENTAL
23 #else
25 #endif
26 #endif
27 #if SYCL_EXT_ONEAPI_BACKEND_HIP
29 #endif
30 #if SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO
32 #endif
35 #include <CL/sycl/detail/pi.h>
36 #include <CL/sycl/detail/pi.hpp>
37 #include <CL/sycl/device.hpp>
38 #include <CL/sycl/event.hpp>
39 #include <CL/sycl/exception.hpp>
41 #include <CL/sycl/platform.hpp>
42 #include <CL/sycl/queue.hpp>
43 
44 #include <type_traits>
45 
47 namespace sycl {
48 
49 namespace detail {
50 // TODO each backend can have its own custom errc enumeration
51 // but the details for this are not fully specified yet
52 enum class backend_errc : unsigned int {};
53 } // namespace detail
54 
55 template <backend Backend> class backend_traits {
56 public:
57  template <class T>
59 
60  template <class T>
62 
64 };
65 
66 template <backend Backend, typename SyclType>
67 using backend_input_t =
68  typename backend_traits<Backend>::template input_type<SyclType>;
69 
70 template <backend Backend, typename SyclType>
71 using backend_return_t =
72  typename backend_traits<Backend>::template return_type<SyclType>;
73 
74 namespace detail {
75 template <backend Backend, typename DataT, int Dimensions, typename AllocatorT>
76 struct BufferInterop {
77  using ReturnType =
79 
80  static ReturnType GetNativeObjs(const std::vector<pi_native_handle> &Handle) {
81  ReturnType ReturnValue = 0;
82  if (Handle.size()) {
83  ReturnValue = detail::pi::cast<ReturnType>(Handle[0]);
84  }
85  return ReturnValue;
86  }
87 };
88 
89 #ifdef SYCL2020_CONFORMANT_APIS
90 template <typename DataT, int Dimensions, typename AllocatorT>
91 struct BufferInterop<backend::opencl, DataT, Dimensions, AllocatorT> {
92  using ReturnType =
94 
95  static ReturnType GetNativeObjs(const std::vector<pi_native_handle> &Handle) {
96  ReturnType ReturnValue{};
97  for (auto &Obj : Handle) {
98  ReturnValue.push_back(
99  detail::pi::cast<typename decltype(ReturnValue)::value_type>(Obj));
100  }
101  return ReturnValue;
102  }
103 };
104 #endif
105 
106 template <backend BackendName, typename DataT, int Dimensions,
107  typename AllocatorT>
109  -> backend_return_t<BackendName,
111  // No check for backend mismatch because buffer can be allocated on different
112  // backends
113  if (BackendName == backend::ext_oneapi_level_zero)
114  throw sycl::runtime_error(
115  errc::feature_not_supported,
116  "Buffer interop is not supported by level zero yet",
117  PI_ERROR_INVALID_OPERATION);
118  return Obj.template getNative<BackendName>();
119 }
120 } // namespace detail
121 
122 template <backend BackendName, class SyclObjectT>
123 auto get_native(const SyclObjectT &Obj)
125  // TODO use SYCL 2020 exception when implemented
126  if (Obj.get_backend() != BackendName) {
127  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
128  PI_ERROR_INVALID_OPERATION);
129  }
130  return Obj.template get_native<BackendName>();
131 }
132 
133 template <backend BackendName, typename DataT, int Dimensions,
134  typename AllocatorT,
135  std::enable_if_t<BackendName == backend::opencl> * = nullptr>
136 #ifndef SYCL2020_CONFORMANT_APIS
138  "get_native<backend::opencl, buffer>, which return type "
139  "cl_mem is deprecated. According to SYCL 2020 spec, please define "
140  "SYCL2020_CONFORMANT_APIS and use vector<cl_mem> instead.")
141 #endif
144  return detail::get_native_buffer<BackendName>(Obj);
145 }
146 
147 template <backend BackendName, typename DataT, int Dimensions,
148  typename AllocatorT,
149  std::enable_if_t<BackendName != backend::opencl> * = nullptr>
152  return detail::get_native_buffer<BackendName>(Obj);
153 }
154 
155 // define SYCL2020_CONFORMANT_APIS to correspond SYCL 2020 spec and return
156 // vector<cl_event> from get_native instead of just cl_event
157 #ifdef SYCL2020_CONFORMANT_APIS
158 template <>
159 inline backend_return_t<backend::opencl, event>
160 get_native<backend::opencl, event>(const event &Obj) {
161  // TODO use SYCL 2020 exception when implemented
162  if (Obj.get_backend() != backend::opencl) {
163  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
164  PI_ERROR_INVALID_OPERATION);
165  }
166  backend_return_t<backend::opencl, event> ReturnValue;
167  for (auto const &element : Obj.getNativeVector()) {
168  ReturnValue.push_back(
169  reinterpret_cast<
170  typename detail::interop<backend::opencl, event>::value_type>(
171  element));
172  }
173  return ReturnValue;
174 }
175 #else
176 // Specialization for cl_event with deprecation message
177 template <>
179  "get_native<backend::opencl, event>, which return type is "
180  "cl_event is deprecated. According to SYCL 2020 spec, please define "
181  "SYCL2020_CONFORMANT_APIS and use vector<cl_event> instead.")
182 inline backend_return_t<backend::opencl, event> get_native<
183  backend::opencl, event>(const event &Obj) {
184  // TODO use SYCL 2020 exception when implemented
185  if (Obj.get_backend() != backend::opencl) {
186  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
187  PI_ERROR_INVALID_OPERATION);
188  }
189  return reinterpret_cast<
190  typename detail::interop<backend::opencl, event>::type>(Obj.getNative());
191 }
192 #endif
193 
194 // Native handle of an accessor should be accessed through interop_handler
195 template <backend BackendName, typename DataT, int Dimensions,
196  access::mode AccessMode, access::target AccessTarget,
197  access::placeholder IsPlaceholder>
198 auto get_native(const accessor<DataT, Dimensions, AccessMode, AccessTarget,
199  IsPlaceholder> &Obj) ->
200  typename detail::interop<
201  BackendName, accessor<DataT, Dimensions, AccessMode, AccessTarget,
202  IsPlaceholder>>::type = delete;
203 
204 namespace detail {
205 // Forward declaration
206 class kernel_bundle_impl;
207 
208 __SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle,
209  backend Backend);
210 __SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
211  backend Backend);
212 __SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
213  const async_handler &Handler,
214  backend Backend);
215 __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
216  const context &TargetContext,
217  const device &TargetDevice, bool KeepOwnership,
218  const async_handler &Handler, backend Backend);
219 // TODO: Unused. Remove when allowed.
220 __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
221  const context &TargetContext, bool KeepOwnership,
222  const async_handler &Handler, backend Backend);
223 __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
224  const context &TargetContext,
225  const async_handler &Handler, backend Backend);
226 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
227  const context &TargetContext, backend Backend);
228 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
229  const context &TargetContext, bool KeepOwnership,
230  backend Backend);
231 // TODO: Unused. Remove when allowed.
232 __SYCL_EXPORT kernel make_kernel(pi_native_handle NativeHandle,
233  const context &TargetContext, backend Backend);
234 __SYCL_EXPORT kernel make_kernel(
235  const context &TargetContext,
236  const kernel_bundle<bundle_state::executable> &KernelBundle,
237  pi_native_handle NativeKernelHandle, bool KeepOwnership, backend Backend);
238 // TODO: Unused. Remove when allowed.
239 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
240 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
241  bundle_state State, backend Backend);
242 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
243 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
244  bool KeepOwnership, bundle_state State, backend Backend);
245 } // namespace detail
246 
247 template <backend Backend>
248 typename std::enable_if<
249  detail::InteropFeatureSupportMap<Backend>::MakePlatform == true,
250  platform>::type
252  const typename backend_traits<Backend>::template input_type<platform>
253  &BackendObject) {
254  return detail::make_platform(
255  detail::pi::cast<pi_native_handle>(BackendObject), Backend);
256 }
257 
258 template <backend Backend>
259 typename std::enable_if<
260  detail::InteropFeatureSupportMap<Backend>::MakeDevice == true, device>::type
261 make_device(const typename backend_traits<Backend>::template input_type<device>
262  &BackendObject) {
263  return detail::make_device(detail::pi::cast<pi_native_handle>(BackendObject),
264  Backend);
265 }
266 
267 template <backend Backend>
268 typename std::enable_if<
269  detail::InteropFeatureSupportMap<Backend>::MakeContext == true,
270  context>::type
272  const typename backend_traits<Backend>::template input_type<context>
273  &BackendObject,
274  const async_handler &Handler = {}) {
275  return detail::make_context(detail::pi::cast<pi_native_handle>(BackendObject),
276  Handler, Backend);
277 }
278 
279 template <backend Backend>
280 __SYCL_DEPRECATED("Use SYCL 2020 sycl::make_queue free function")
281 typename std::enable_if<
282  detail::InteropFeatureSupportMap<Backend>::MakeQueue == true, queue>::type
284  const typename backend_traits<Backend>::template input_type<queue>
285  &BackendObject,
286  const context &TargetContext, bool KeepOwnership,
287  const async_handler Handler = {}) {
288  return detail::make_queue(detail::pi::cast<pi_native_handle>(BackendObject),
289  TargetContext, KeepOwnership, Handler, Backend);
290 }
291 
292 template <backend Backend>
293 typename std::enable_if<
294  detail::InteropFeatureSupportMap<Backend>::MakeQueue == true, queue>::type
295 make_queue(const typename backend_traits<Backend>::template input_type<queue>
296  &BackendObject,
297  const context &TargetContext, const async_handler Handler = {}) {
298  return detail::make_queue(detail::pi::cast<pi_native_handle>(BackendObject),
299  TargetContext, false, Handler, Backend);
300 }
301 
302 template <backend Backend>
303 typename std::enable_if<
304  detail::InteropFeatureSupportMap<Backend>::MakeEvent == true, event>::type
305 make_event(const typename backend_traits<Backend>::template input_type<event>
306  &BackendObject,
307  const context &TargetContext) {
308  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
309  TargetContext, Backend);
310 }
311 
312 template <backend Backend>
313 __SYCL_DEPRECATED("Use SYCL 2020 sycl::make_event free function")
314 typename std::enable_if<
315  detail::InteropFeatureSupportMap<Backend>::MakeEvent == true, event>::type
317  const typename backend_traits<Backend>::template input_type<event>
318  &BackendObject,
319  const context &TargetContext, bool KeepOwnership) {
320  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
321  TargetContext, KeepOwnership, Backend);
322 }
323 
324 template <backend Backend, typename T, int Dimensions = 1,
325  typename AllocatorT = detail::default_buffer_allocator<T>>
326 typename std::enable_if<detail::InteropFeatureSupportMap<Backend>::MakeBuffer ==
327  true &&
328  Backend != backend::ext_oneapi_level_zero,
329  buffer<T, Dimensions, AllocatorT>>::type
331  buffer<T, Dimensions, AllocatorT>> &BackendObject,
332  const context &TargetContext, event AvailableEvent = {}) {
333  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
334  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
335  AvailableEvent);
336 }
337 
338 template <backend Backend>
339 kernel
340 make_kernel(const typename backend_traits<Backend>::template input_type<kernel>
341  &BackendObject,
342  const context &TargetContext) {
343  return detail::make_kernel(detail::pi::cast<pi_native_handle>(BackendObject),
344  TargetContext, Backend);
345 }
346 
347 template <backend Backend, bundle_state State>
348 typename std::enable_if<
349  detail::InteropFeatureSupportMap<Backend>::MakeKernelBundle == true,
350  kernel_bundle<State>>::type
352  kernel_bundle<State>> &BackendObject,
353  const context &TargetContext) {
354  std::shared_ptr<detail::kernel_bundle_impl> KBImpl =
356  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
357  false, State, Backend);
358  return detail::createSyclObjFromImpl<kernel_bundle<State>>(KBImpl);
359 }
360 } // namespace sycl
361 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::backend
backend
Definition: backend_types.hpp:21
cl::sycl::make_context
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeContext==true, context >::type make_context(const typename backend_traits< Backend >::template input_type< context > &BackendObject, const async_handler &Handler={})
Definition: backend.hpp:271
backend_traits_opencl.hpp
pi.h
cl::sycl::kernel_bundle
The kernel_bundle class represents collection of device images in a particular state.
Definition: kernel.hpp:29
cl::sycl::make_queue
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeQueue==true, queue >::type make_queue(const typename backend_traits< Backend >::template input_type< queue > &BackendObject, const context &TargetContext, const async_handler Handler={})
Definition: backend.hpp:295
cl::sycl::backend_return_t
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:72
cl::sycl::event
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:32
backend_traits_cuda.hpp
cl::sycl::make_event
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeEvent==true, event >::type make_event(const typename backend_traits< Backend >::template input_type< event > &BackendObject, const context &TargetContext, bool KeepOwnership)
Definition: backend.hpp:316
cl::sycl::access::placeholder
placeholder
Definition: access.hpp:43
cl::sycl::backend::opencl
@ opencl
device.hpp
__SYCL_DEPRECATED
#define __SYCL_DEPRECATED(message)
Definition: defines_elementary.hpp:47
cl::sycl::detail::BufferInterop
Definition: backend.hpp:76
backend_traits_cuda.hpp
context.hpp
event.hpp
cl::sycl::backend_traits
Definition: backend.hpp:55
cl::sycl::detail::backend_errc
backend_errc
Definition: backend.hpp:52
sycl
Definition: invoke_simd.hpp:68
cl::sycl::make_kernel
kernel make_kernel(const typename backend_traits< Backend >::template input_type< kernel > &BackendObject, const context &TargetContext)
Definition: backend.hpp:340
cl::sycl::queue
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:103
pi.hpp
cast
To cast(From value)
Definition: pi_opencl.cpp:41
cl::sycl::buffer
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:78
cl::sycl::bundle_state
bundle_state
Definition: kernel_bundle_enums.hpp:14
backend_traits.hpp
cl::sycl::info::event
event
Definition: info_desc.hpp:289
cl::sycl::info::queue
queue
Definition: info_desc.hpp:229
cl::sycl::detail::BufferInterop::GetNativeObjs
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:80
cl::sycl::backend_traits::input_type
typename detail::BackendInput< Backend, T >::type input_type
Definition: backend.hpp:58
export.hpp
backend_traits_level_zero.hpp
kernel_bundle.hpp
cl::sycl::backend_traits::return_type
typename detail::BackendReturn< Backend, T >::type return_type
Definition: backend.hpp:61
cl::sycl::access::target
target
Definition: access.hpp:17
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
queue.hpp
cl::sycl::detail::interop
Definition: backend_traits.hpp:18
backend_traits_hip.hpp
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:98
accessor.hpp
cl::sycl::info::context
context
Definition: info_desc.hpp:42
cl::sycl::detail::BufferInterop::ReturnType
backend_return_t< Backend, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:78
cl::sycl::detail::get_native_buffer
auto get_native_buffer(const buffer< DataT, Dimensions, AllocatorT, void > &Obj) -> backend_return_t< BackendName, buffer< DataT, Dimensions, AllocatorT, void >>
Definition: backend.hpp:108
backend_types.hpp
platform.hpp
exception.hpp
std
Definition: accessor.hpp:2617
cl::sycl::backend_input_t
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:68
cl::sycl::make_kernel_bundle
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeKernelBundle==true, kernel_bundle< State > >::type make_kernel_bundle(const typename backend_traits< Backend >::template input_type< kernel_bundle< State >> &BackendObject, const context &TargetContext)
Definition: backend.hpp:351
cl::sycl::context
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:38
feature_test.hpp
buffer.hpp
cl::sycl::get_native
auto get_native(const accessor< DataT, Dimensions, AccessMode, AccessTarget, IsPlaceholder > &Obj) -> typename detail::interop< BackendName, accessor< DataT, Dimensions, AccessMode, AccessTarget, IsPlaceholder >>::type=delete
common.hpp
cl::sycl::make_platform
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakePlatform==true, platform >::type make_platform(const typename backend_traits< Backend >::template input_type< platform > &BackendObject)
Definition: backend.hpp:251
cl::sycl::info::platform
platform
Definition: info_desc.hpp:31
cl::sycl::access::mode
mode
Definition: access.hpp:28
cl::sycl::info::device
device
Definition: info_desc.hpp:53
cl::sycl::make_buffer
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeBuffer==true &&Backend !=backend::ext_oneapi_level_zero, buffer< T, Dimensions, AllocatorT > >::type make_buffer(const typename backend_traits< Backend >::template input_type< buffer< T, Dimensions, AllocatorT >> &BackendObject, const context &TargetContext, event AvailableEvent={})
Definition: backend.hpp:330
cl::sycl::async_handler
std::function< void(cl::sycl::exception_list)> async_handler
Definition: exception_list.hpp:53
cl::sycl::Dimensions
Dimensions
Definition: backend.hpp:142
cl::sycl::detail::BackendReturn
Definition: backend_traits.hpp:22
cl::sycl::detail::BackendInput
Definition: backend_traits.hpp:20
cl::sycl::make_device
std::enable_if< detail::InteropFeatureSupportMap< Backend >::MakeDevice==true, device >::type make_device(const typename backend_traits< Backend >::template input_type< device > &BackendObject)
Definition: backend.hpp:261
cl::sycl::info::kernel
kernel
Definition: info_desc.hpp:236
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12