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/accessor.hpp>
12 #include <sycl/backend_types.hpp>
13 #include <sycl/buffer.hpp>
14 #include <sycl/context.hpp>
16 #include <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
33 #include <sycl/detail/common.hpp>
34 #include <sycl/detail/export.hpp>
35 #include <sycl/detail/pi.h>
36 #include <sycl/detail/pi.hpp>
37 #include <sycl/device.hpp>
38 #include <sycl/event.hpp>
39 #include <sycl/exception.hpp>
40 #include <sycl/kernel_bundle.hpp>
41 #include <sycl/platform.hpp>
42 #include <sycl/queue.hpp>
43 
44 #include <type_traits>
45 
46 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>
68  typename backend_traits<Backend>::template input_type<SyclType>;
69 
70 template <backend Backend, typename SyclType>
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 template <typename DataT, int Dimensions, typename AllocatorT>
90 struct BufferInterop<backend::opencl, DataT, Dimensions, AllocatorT> {
91  using ReturnType =
93 
94  static ReturnType GetNativeObjs(const std::vector<pi_native_handle> &Handle) {
95  ReturnType ReturnValue{};
96  for (auto &Obj : Handle) {
97  ReturnValue.push_back(
98  detail::pi::cast<typename decltype(ReturnValue)::value_type>(Obj));
99  }
100  return ReturnValue;
101  }
102 };
103 
104 #if SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO
105 template <backend BackendName, typename DataT, int Dimensions,
106  typename AllocatorT>
108  -> backend_return_t<BackendName,
110  // No check for backend mismatch because buffer can be allocated on different
111  // backends
112  if (BackendName == backend::ext_oneapi_level_zero)
113  throw sycl::runtime_error(
114  errc::feature_not_supported,
115  "Buffer interop is not supported by level zero yet",
116  PI_ERROR_INVALID_OPERATION);
117  return Obj.template getNative<BackendName>();
118 }
119 #endif
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 reinterpret_cast<backend_return_t<BackendName, SyclObjectT>>(
131  Obj.getNative());
132 }
133 
134 template <backend BackendName, bundle_state State>
137  // TODO use SYCL 2020 exception when implemented
138  if (Obj.get_backend() != BackendName) {
139  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
140  PI_ERROR_INVALID_OPERATION);
141  }
142  return Obj.template getNative<BackendName>();
143 }
144 
145 template <backend BackendName, typename DataT, int Dimensions,
146  typename AllocatorT>
149  return detail::get_native_buffer<BackendName>(Obj);
150 }
151 
152 #if SYCL_BACKEND_OPENCL
153 template <>
154 inline backend_return_t<backend::opencl, event>
155 get_native<backend::opencl, event>(const event &Obj) {
156  // TODO use SYCL 2020 exception when implemented
157  if (Obj.get_backend() != backend::opencl) {
158  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
159  PI_ERROR_INVALID_OPERATION);
160  }
161  backend_return_t<backend::opencl, event> ReturnValue;
162  for (auto const &element : Obj.getNativeVector()) {
163  ReturnValue.push_back(
164  reinterpret_cast<
165  typename detail::interop<backend::opencl, event>::value_type>(
166  element));
167  }
168  return ReturnValue;
169 }
170 #endif
171 
172 #if SYCL_EXT_ONEAPI_BACKEND_CUDA
173 template <>
174 inline backend_return_t<backend::ext_oneapi_cuda, device>
175 get_native<backend::ext_oneapi_cuda, device>(const device &Obj) {
176  // TODO use SYCL 2020 exception when implemented
177  if (Obj.get_backend() != backend::ext_oneapi_cuda) {
178  throw sycl::runtime_error(errc::backend_mismatch, "Backends mismatch",
179  PI_ERROR_INVALID_OPERATION);
180  }
181  // CUDA uses a 32-bit int instead of an opaque pointer like other backends,
182  // so we need a specialization with static_cast instead of reinterpret_cast.
183  return static_cast<backend_return_t<backend::ext_oneapi_cuda, device>>(
184  Obj.getNative());
185 }
186 #endif
187 
188 // Native handle of an accessor should be accessed through interop_handler
189 template <backend BackendName, typename DataT, int Dimensions,
190  access::mode AccessMode, access::target AccessTarget,
192 auto get_native(const accessor<DataT, Dimensions, AccessMode, AccessTarget,
193  IsPlaceholder> &Obj) ->
194  typename detail::interop<
195  BackendName, accessor<DataT, Dimensions, AccessMode, AccessTarget,
196  IsPlaceholder>>::type = delete;
197 
198 namespace detail {
199 // Forward declaration
200 class kernel_bundle_impl;
201 
202 __SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle,
203  backend Backend);
204 __SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
205  backend Backend);
206 __SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
207  const async_handler &Handler,
208  backend Backend);
209 __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
210  const context &TargetContext,
211  const device *TargetDevice, bool KeepOwnership,
212  const async_handler &Handler, backend Backend);
213 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
214  const context &TargetContext, backend Backend);
215 __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
216  const context &TargetContext, bool KeepOwnership,
217  backend Backend);
218 // TODO: Unused. Remove when allowed.
219 __SYCL_EXPORT kernel make_kernel(pi_native_handle NativeHandle,
220  const context &TargetContext, backend Backend);
221 __SYCL_EXPORT kernel make_kernel(
222  const context &TargetContext,
223  const kernel_bundle<bundle_state::executable> &KernelBundle,
224  pi_native_handle NativeKernelHandle, bool KeepOwnership, backend Backend);
225 // TODO: Unused. Remove when allowed.
226 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
227 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
228  bundle_state State, backend Backend);
229 __SYCL_EXPORT std::shared_ptr<detail::kernel_bundle_impl>
230 make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
231  bool KeepOwnership, bundle_state State, backend Backend);
232 } // namespace detail
233 
234 template <backend Backend>
235 typename std::enable_if<
236  detail::InteropFeatureSupportMap<Backend>::MakePlatform == true,
237  platform>::type
239  const typename backend_traits<Backend>::template input_type<platform>
240  &BackendObject) {
241  return detail::make_platform(
242  detail::pi::cast<pi_native_handle>(BackendObject), Backend);
243 }
244 
245 template <backend Backend>
246 typename std::enable_if<
247  detail::InteropFeatureSupportMap<Backend>::MakeDevice == true, device>::type
248 make_device(const typename backend_traits<Backend>::template input_type<device>
249  &BackendObject) {
250  return detail::make_device(detail::pi::cast<pi_native_handle>(BackendObject),
251  Backend);
252 }
253 
254 template <backend Backend>
255 typename std::enable_if<
256  detail::InteropFeatureSupportMap<Backend>::MakeContext == true,
257  context>::type
259  const typename backend_traits<Backend>::template input_type<context>
260  &BackendObject,
261  const async_handler &Handler = {}) {
262  return detail::make_context(detail::pi::cast<pi_native_handle>(BackendObject),
263  Handler, Backend);
264 }
265 
266 template <backend Backend>
267 typename std::enable_if<
268  detail::InteropFeatureSupportMap<Backend>::MakeQueue == true, queue>::type
269 make_queue(const typename backend_traits<Backend>::template input_type<queue>
270  &BackendObject,
271  const context &TargetContext, const async_handler Handler = {}) {
272  return detail::make_queue(detail::pi::cast<pi_native_handle>(BackendObject),
273  TargetContext, nullptr, false, Handler, Backend);
274 }
275 
276 template <backend Backend>
277 typename std::enable_if<
278  detail::InteropFeatureSupportMap<Backend>::MakeEvent == true, event>::type
279 make_event(const typename backend_traits<Backend>::template input_type<event>
280  &BackendObject,
281  const context &TargetContext) {
282  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
283  TargetContext, Backend);
284 }
285 
286 template <backend Backend>
287 __SYCL_DEPRECATED("Use SYCL 2020 sycl::make_event free function")
288 typename std::enable_if<
289  detail::InteropFeatureSupportMap<Backend>::MakeEvent == true, event>::type
291  const typename backend_traits<Backend>::template input_type<event>
292  &BackendObject,
293  const context &TargetContext, bool KeepOwnership) {
294  return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
295  TargetContext, KeepOwnership, Backend);
296 }
297 
298 template <backend Backend, typename T, int Dimensions = 1,
299  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
300 typename std::enable_if<detail::InteropFeatureSupportMap<Backend>::MakeBuffer ==
301  true &&
302  Backend != backend::ext_oneapi_level_zero,
303  buffer<T, Dimensions, AllocatorT>>::type
305  buffer<T, Dimensions, AllocatorT>> &BackendObject,
306  const context &TargetContext, event AvailableEvent = {}) {
307  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
308  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
309  AvailableEvent);
310 }
311 
312 template <backend Backend>
313 kernel
314 make_kernel(const typename backend_traits<Backend>::template input_type<kernel>
315  &BackendObject,
316  const context &TargetContext) {
317  return detail::make_kernel(detail::pi::cast<pi_native_handle>(BackendObject),
318  TargetContext, Backend);
319 }
320 
321 template <backend Backend, bundle_state State>
322 typename std::enable_if<
323  detail::InteropFeatureSupportMap<Backend>::MakeKernelBundle == true,
324  kernel_bundle<State>>::type
326  kernel_bundle<State>> &BackendObject,
327  const context &TargetContext) {
328  std::shared_ptr<detail::kernel_bundle_impl> KBImpl =
330  detail::pi::cast<pi_native_handle>(BackendObject), TargetContext,
331  false, State, Backend);
332  return detail::createSyclObjFromImpl<kernel_bundle<State>>(KBImpl);
333 }
334 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
335 } // namespace sycl
The file contains implementations of accessor class.
typename detail::BackendReturn< Backend, T >::type return_type
Definition: backend.hpp:61
typename detail::BackendInput< Backend, T >::type input_type
Definition: backend.hpp:58
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:137
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:39
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:47
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:38
The kernel_bundle class represents collection of device images in a particular state.
Provides an abstraction of a SYCL kernel.
Definition: kernel.hpp:69
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:45
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:86
#define __SYCL_INLINE_VER_NAMESPACE(X)
#define __SYCL_DEPRECATED(message)
auto get_native_buffer(const buffer< DataT, Dimensions, AllocatorT, void > &Obj) -> backend_return_t< BackendName, buffer< DataT, Dimensions, AllocatorT, void >>
Definition: backend.hpp:107
class __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_SPECIAL_CLASS IsPlaceholder
Definition: accessor.hpp:2749
class __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:2747
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:325
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:290
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:72
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:248
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:258
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:304
kernel make_kernel(const typename backend_traits< Backend >::template input_type< kernel > &BackendObject, const context &TargetContext)
Definition: backend.hpp:314
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:238
auto get_native(const accessor< DataT, Dimensions, AccessMode, AccessTarget, IsPlaceholder > &Obj) -> typename detail::interop< BackendName, accessor< DataT, Dimensions, AccessMode, AccessTarget, IsPlaceholder >>::type=delete
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:269
std::function< void(sycl::exception_list)> async_handler
class __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_SPECIAL_CLASS AccessMode
Definition: accessor.hpp:2747
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:68
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
uintptr_t pi_native_handle
Definition: pi.h:107
C++ wrapper of extern "C" PI interfaces.
To cast(From value)
Definition: pi_opencl.cpp:42
backend_return_t< backend::opencl, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:92
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:94
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:80
backend_return_t< Backend, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:78