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 <sycl/access/access.hpp> // for mode, placeholder
12 #include <sycl/accessor.hpp> // for accessor
13 #include <sycl/async_handler.hpp> // for async_handler
14 #include <sycl/backend_types.hpp> // for backend
15 #include <sycl/buffer.hpp> // for buffer_allocator
16 #include <sycl/context.hpp> // for context, get_na...
17 #include <sycl/detail/backend_traits.hpp> // for InteropFeatureS...
18 #include <sycl/detail/cl.h> // for _cl_event
19 #include <sycl/detail/defines_elementary.hpp> // for __SYCL_DEPRECATED
20 #include <sycl/detail/export.hpp> // for __SYCL_EXPORT
21 #include <sycl/detail/impl_utils.hpp> // for createSyclObjFr...
22 #include <sycl/detail/pi.h> // for pi_native_handle
23 #include <sycl/device.hpp> // for device, get_native
24 #include <sycl/event.hpp> // for event, get_native
25 #include <sycl/exception.hpp> // for make_error_code
26 #include <sycl/feature_test.hpp> // for SYCL_BACKEND_OP...
27 #include <sycl/handler.hpp> // for buffer
28 #include <sycl/image.hpp> // for image, image_al...
29 #include <sycl/kernel.hpp> // for kernel, get_native
30 #include <sycl/kernel_bundle.hpp> // for kernel_bundle
31 #include <sycl/kernel_bundle_enums.hpp> // for bundle_state
32 #include <sycl/platform.hpp> // for platform, get_n...
33 #include <sycl/property_list.hpp> // for property_list
34 #include <sycl/queue.hpp> // for queue, get_native
35 
36 #if SYCL_BACKEND_OPENCL
37 #include <sycl/detail/backend_traits_opencl.hpp> // for interop
38 #endif
39 #if SYCL_EXT_ONEAPI_BACKEND_CUDA
40 #ifdef SYCL_EXT_ONEAPI_BACKEND_CUDA_EXPERIMENTAL
42 #else
44 #endif
45 #endif
46 #if SYCL_EXT_ONEAPI_BACKEND_HIP
48 #endif
49 #if SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO
50 #include <sycl/detail/backend_traits_level_zero.hpp> // for _ze_command_lis...
51 #endif
52 
53 #include <memory> // for shared_ptr
54 #include <stdint.h> // for int32_t
55 #include <type_traits> // for enable_if_t
56 #include <vector> // for vector
57 
58 namespace sycl {
59 inline namespace _V1 {
60 
61 namespace detail {
62 // TODO each backend can have its own custom errc enumeration
63 // but the details for this are not fully specified yet
64 enum class backend_errc : unsigned int {};
65 
66 // Convert from PI backend to SYCL backend enum
68 } // namespace detail
69 
70 template <backend Backend> class backend_traits {
71 public:
72  template <class T>
74 
75  template <class T>
77 
79 };
80 
81 template <backend Backend, typename SyclType>
83  typename backend_traits<Backend>::template input_type<SyclType>;
84 
85 template <backend Backend, typename SyclType>
87  typename backend_traits<Backend>::template return_type<SyclType>;
88 
89 namespace detail {
90 template <backend Backend, typename DataT, int Dimensions, typename AllocatorT>
91 struct BufferInterop {
92  using ReturnType =
94 
95  static ReturnType GetNativeObjs(const std::vector<pi_native_handle> &Handle) {
96  ReturnType ReturnValue = 0;
97  if (Handle.size()) {
98  ReturnValue = detail::pi::cast<ReturnType>(Handle[0]);
99  }
100  return ReturnValue;
101  }
102 };
103 
104 template <typename DataT, int Dimensions, typename AllocatorT>
105 struct BufferInterop<backend::opencl, DataT, Dimensions, AllocatorT> {
106  using ReturnType =
108 
109  static ReturnType GetNativeObjs(const std::vector<pi_native_handle> &Handle) {
110  ReturnType ReturnValue{};
111  for (auto &Obj : Handle) {
112  ReturnValue.push_back(
113  detail::pi::cast<typename decltype(ReturnValue)::value_type>(Obj));
114  }
115  return ReturnValue;
116  }
117 };
118 
119 #if SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO
120 template <backend BackendName, typename DataT, int Dimensions,
121  typename AllocatorT>
123  -> backend_return_t<BackendName,
125  // No check for backend mismatch because buffer can be allocated on different
126  // backends
127  if (BackendName == backend::ext_oneapi_level_zero)
129  "Buffer interop is not supported by level zero yet");
130  return Obj.template getNative<BackendName>();
131 }
132 #endif
133 } // namespace detail
134 
135 template <backend BackendName, class SyclObjectT>
136 auto get_native(const SyclObjectT &Obj)
138  if (Obj.get_backend() != BackendName) {
140  "Backends mismatch");
141  }
142  return reinterpret_cast<backend_return_t<BackendName, SyclObjectT>>(
143  Obj.getNative());
144 }
145 
146 template <backend BackendName>
148  if (Obj.get_backend() != BackendName) {
150  "Backends mismatch");
151  }
152  int32_t IsImmCmdList;
153  pi_native_handle Handle = Obj.getNative(IsImmCmdList);
155  if constexpr (BackendName == backend::ext_oneapi_level_zero)
156  RetVal = IsImmCmdList
157  ? backend_return_t<BackendName, queue>{reinterpret_cast<
158  ze_command_list_handle_t>(Handle)}
160  reinterpret_cast<ze_command_queue_handle_t>(Handle)};
161  else
162  RetVal = reinterpret_cast<backend_return_t<BackendName, queue>>(Handle);
163 
164  return RetVal;
165 }
166 
167 template <backend BackendName, bundle_state State>
170  if (Obj.get_backend() != BackendName) {
172  "Backends mismatch");
173  }
174  return Obj.template getNative<BackendName>();
175 }
176 
177 template <backend BackendName, typename DataT, int Dimensions,
178  typename AllocatorT>
181  return detail::get_native_buffer<BackendName>(Obj);
182 }
183 
184 #if SYCL_BACKEND_OPENCL
185 template <>
186 inline backend_return_t<backend::opencl, event>
187 get_native<backend::opencl, event>(const event &Obj) {
188  if (Obj.get_backend() != backend::opencl) {
190  "Backends mismatch");
191  }
192  backend_return_t<backend::opencl, event> ReturnValue;
193  for (auto const &element : Obj.getNativeVector()) {
194  ReturnValue.push_back(
195  reinterpret_cast<
197  element));
198  }
199  return ReturnValue;
200 }
201 #endif
202 
203 #if SYCL_EXT_ONEAPI_BACKEND_CUDA
204 template <>
205 inline backend_return_t<backend::ext_oneapi_cuda, device>
206 get_native<backend::ext_oneapi_cuda, device>(const device &Obj) {
207  if (Obj.get_backend() != backend::ext_oneapi_cuda) {
209  "Backends mismatch");
210  }
211  // CUDA uses a 32-bit int instead of an opaque pointer like other backends,
212  // so we need a specialization with static_cast instead of reinterpret_cast.
213  return static_cast<backend_return_t<backend::ext_oneapi_cuda, device>>(
214  Obj.getNative());
215 }
216 
217 #ifndef SYCL_EXT_ONEAPI_BACKEND_CUDA_EXPERIMENTAL
218 template <>
220  "Context interop is deprecated for CUDA. If a native context is required,"
221  " use cuDevicePrimaryCtxRetain with a native device")
222 inline backend_return_t<backend::ext_oneapi_cuda, context> get_native<
223  backend::ext_oneapi_cuda, context>(const context &Obj) {
224  if (Obj.get_backend() != backend::ext_oneapi_cuda) {
226  "Backends mismatch");
227  }
228  return reinterpret_cast<backend_return_t<backend::ext_oneapi_cuda, context>>(
229  Obj.getNative());
230 }
231 
232 #endif // SYCL_EXT_ONEAPI_BACKEND_CUDA_EXPERIMENTAL
233 #endif // SYCL_EXT_ONEAPI_BACKEND_CUDA
234 
235 #if SYCL_EXT_ONEAPI_BACKEND_HIP
236 
237 template <>
239  "Context interop is deprecated for HIP. If a native context is required,"
240  " use hipDevicePrimaryCtxRetain with a native device")
241 inline backend_return_t<backend::ext_oneapi_hip, context> get_native<
242  backend::ext_oneapi_hip, context>(const context &Obj) {
243  if (Obj.get_backend() != backend::ext_oneapi_hip) {
245  "Backends mismatch");
246  }
247  return reinterpret_cast<backend_return_t<backend::ext_oneapi_hip, context>>(
248  Obj.getNative());
249 }
250 
251 #endif // SYCL_EXT_ONEAPI_BACKEND_HIP
252 
253 template <backend BackendName, typename DataT, int Dimensions,
254  access::mode AccessMode, access::target AccessTarget,
256 auto get_native(const accessor<DataT, Dimensions, AccessMode, AccessTarget,
257  IsPlaceholder> &Obj) ->
258  typename detail::interop<
259  BackendName, accessor<DataT, Dimensions, AccessMode, AccessTarget,
260  IsPlaceholder>>::type = delete;
261 
262 namespace detail {
263 // Forward declaration
264 class kernel_bundle_impl;
265 
266 __SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle,
267  backend Backend);
268 __SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
269  backend Backend);
270 __SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
271  const async_handler &Handler,
272  backend Backend);
273 __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
274  int32_t nativeHandleDesc,
275  const context &TargetContext,
276  const device *TargetDevice, bool KeepOwnership,
277  const property_list &PropList,
278  const async_handler &Handler, backend Backend);
279 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
280  const context &TargetContext, backend Backend);
281 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
282  const context &TargetContext, bool KeepOwnership,
283  backend Backend);
284 // TODO: Unused. Remove when allowed.
285 __SYCL_EXPORT kernel make_kernel(pi_native_handle NativeHandle,
286  const context &TargetContext, backend Backend);
287 __SYCL_EXPORT kernel make_kernel(
288  const context &TargetContext,
289  const kernel_bundle<bundle_state::executable> &KernelBundle,
290  pi_native_handle NativeKernelHandle, bool KeepOwnership, backend Backend);
291 // TODO: Unused. Remove when allowed.
292 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
293 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
294  bundle_state State, backend Backend);
295 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
296 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
297  bool KeepOwnership, bundle_state State, backend Backend);
298 } // namespace detail
299 
300 template <backend Backend>
301 std::enable_if_t<
304  const typename backend_traits<Backend>::template input_type<platform>
305  &BackendObject) {
306  return detail::make_platform(
307  detail::pi::cast<pi_native_handle>(BackendObject), Backend);
308 }
309 
310 template <backend Backend>
311 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeDevice == true,
312  device>
313 make_device(const typename backend_traits<Backend>::template input_type<device>
314  &BackendObject) {
315  return detail::make_device(detail::pi::cast<pi_native_handle>(BackendObject),
316  Backend);
317 }
318 
319 template <backend Backend>
320 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeContext == true,
321  context>
323  const typename backend_traits<Backend>::template input_type<context>
324  &BackendObject,
325  const async_handler &Handler = {}) {
326  return detail::make_context(detail::pi::cast<pi_native_handle>(BackendObject),
327  Handler, Backend);
328 }
329 
330 template <backend Backend>
331 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeQueue == true,
332  queue>
333 make_queue(const typename backend_traits<Backend>::template input_type<queue>
334  &BackendObject,
335  const context &TargetContext, const async_handler Handler = {}) {
336  auto KeepOwnership =
337  Backend == backend::ext_oneapi_cuda || Backend == backend::ext_oneapi_hip;
338  return detail::make_queue(detail::pi::cast<pi_native_handle>(BackendObject),
339  false, TargetContext, nullptr, KeepOwnership, {},
340  Handler, Backend);
341 }
342 
343 template <backend Backend>
344 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeEvent == true,
345  event>
346 make_event(const typename backend_traits<Backend>::template input_type<event>
347  &BackendObject,
348  const context &TargetContext) {
349  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
350  TargetContext, Backend);
351 }
352 
353 template <backend Backend>
354 __SYCL_DEPRECATED("Use SYCL 2020 sycl::make_event free function")
355 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeEvent == true,
356  event> make_event(const typename backend_traits<Backend>::
357  template input_type<event>
358  &BackendObject,
359  const context &TargetContext,
360  bool KeepOwnership) {
361  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
362  TargetContext, KeepOwnership, Backend);
363 }
364 
365 template <backend Backend, typename T, int Dimensions = 1,
366  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
367 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeBuffer ==
368  true &&
370  buffer<T, Dimensions, AllocatorT>>
372  buffer<T, Dimensions, AllocatorT>> &BackendObject,
373  const context &TargetContext, event AvailableEvent = {}) {
374  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
375  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
376  AvailableEvent);
377 }
378 
379 template <backend Backend, int Dimensions = 1,
380  typename AllocatorT = image_allocator>
381 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeImage == true &&
383  image<Dimensions, AllocatorT>>
385  image<Dimensions, AllocatorT>> &BackendObject,
386  const context &TargetContext, event AvailableEvent = {}) {
387  return image<Dimensions, AllocatorT>(
388  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
389  AvailableEvent);
390 }
391 
392 template <backend Backend>
393 kernel
394 make_kernel(const typename backend_traits<Backend>::template input_type<kernel>
395  &BackendObject,
396  const context &TargetContext) {
397  return detail::make_kernel(detail::pi::cast<pi_native_handle>(BackendObject),
398  TargetContext, Backend);
399 }
400 
401 template <backend Backend, bundle_state State>
402 std::enable_if_t<detail::InteropFeatureSupportMap<Backend>::MakeKernelBundle ==
403  true,
404  kernel_bundle<State>>
406  kernel_bundle<State>> &BackendObject,
407  const context &TargetContext) {
408  std::shared_ptr<detail::kernel_bundle_impl> KBImpl =
410  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
411  false, State, Backend);
412  return detail::createSyclObjFromImpl<kernel_bundle<State>>(KBImpl);
413 }
414 } // namespace _V1
415 } // namespace sycl
The file contains implementations of accessor class.
struct _ze_command_queue_handle_t * ze_command_queue_handle_t
struct _ze_command_list_handle_t * ze_command_list_handle_t
typename detail::BackendReturn< Backend, T >::type return_type
Definition: backend.hpp:76
typename detail::BackendInput< Backend, T >::type input_type
Definition: backend.hpp:73
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:170
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:51
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:59
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:44
Defines a shared image data.
Definition: image.hpp:444
The kernel_bundle class represents collection of device images in a particular state.
Provides an abstraction of a SYCL kernel.
Definition: kernel.hpp:74
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:63
Objects of the property_list class are containers for the SYCL properties.
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:119
PiProgram cast(cl_program)=delete
backend convertBackend(pi_platform_backend PiBackend)
Definition: backend.cpp:49
context make_context(pi_native_handle NativeHandle, const async_handler &Handler, backend Backend)
Definition: backend.cpp:94
kernel make_kernel(pi_native_handle NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:295
queue make_queue(pi_native_handle NativeHandle, int32_t nativeHandleDesc, const context &TargetContext, const device *TargetDevice, bool KeepOwnership, const property_list &PropList, const async_handler &Handler, backend Backend)
Definition: backend.cpp:107
auto get_native_buffer(const buffer< DataT, Dimensions, Allocator, void > &Obj) -> backend_return_t< BackendName, buffer< DataT, Dimensions, Allocator, void >>
platform make_platform(pi_native_handle NativeHandle, backend Backend)
Definition: backend.cpp:70
device make_device(pi_native_handle NativeHandle, backend Backend)
Definition: backend.cpp:82
event make_event(pi_native_handle NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:141
std::shared_ptr< detail::kernel_bundle_impl > make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext, bundle_state State, backend Backend)
Definition: backend.cpp:247
sycl::detail::kernel_bundle_impl kernel_bundle_impl
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeQueue==true, queue > make_queue(const typename backend_traits< Backend >::template input_type< queue > &BackendObject, const context &TargetContext, const async_handler Handler={})
Definition: backend.hpp:333
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeDevice==true, device > make_device(const typename backend_traits< Backend >::template input_type< device > &BackendObject)
Definition: backend.hpp:313
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeKernelBundle==true, kernel_bundle< State > > make_kernel_bundle(const typename backend_traits< Backend >::template input_type< kernel_bundle< State >> &BackendObject, const context &TargetContext)
Definition: backend.hpp:405
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:3235
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeEvent==true, event > make_event(const typename backend_traits< Backend >::template input_type< event > &BackendObject, const context &TargetContext)
Definition: backend.hpp:346
auto get_native(const SyclObjectT &Obj) -> backend_return_t< BackendName, SyclObjectT >
Definition: backend.hpp:136
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:87
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeImage==true &&Backend !=backend::ext_oneapi_level_zero, image< Dimensions, AllocatorT > > make_image(const typename backend_traits< Backend >::template input_type< image< Dimensions, AllocatorT >> &BackendObject, const context &TargetContext, event AvailableEvent={})
Definition: backend.hpp:384
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS IsPlaceholder
Definition: accessor.hpp:3236
kernel make_kernel(const typename backend_traits< Backend >::template input_type< kernel > &BackendObject, const context &TargetContext)
Definition: backend.hpp:394
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakePlatform==true, platform > make_platform(const typename backend_traits< Backend >::template input_type< platform > &BackendObject)
Definition: backend.hpp:303
std::function< void(sycl::exception_list)> async_handler
__SYCL_DEPRECATED("This is a deprecated argument type for SYCL nan built-in function.") std
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS AccessMode
Definition: accessor.hpp:3235
detail::aligned_allocator< byte > image_allocator
Definition: image.hpp:110
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeContext==true, context > make_context(const typename backend_traits< Backend >::template input_type< context > &BackendObject, const async_handler &Handler={})
Definition: backend.hpp:322
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:94
std::enable_if_t< detail::InteropFeatureSupportMap< Backend >::MakeBuffer==true &&Backend !=backend::ext_oneapi_level_zero, buffer< T, Dimensions, AllocatorT > > make_buffer(const typename backend_traits< Backend >::template input_type< buffer< T, Dimensions, AllocatorT >> &BackendObject, const context &TargetContext, event AvailableEvent={})
Definition: backend.hpp:371
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:83
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:204
_pi_platform_backend
Definition: pi.h:270
backend_return_t< backend::opencl, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:107
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:109
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:95
backend_return_t< Backend, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:93