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>
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 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
sycl::_V1::IsPlaceholder
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS IsPlaceholder
Definition: accessor.hpp:2855
sycl::_V1::access::mode
mode
Definition: access.hpp:30
backend_traits_opencl.hpp
pi.h
sycl::_V1::errc::platform
@ platform
sycl::_V1::backend
backend
Definition: backend_types.hpp:21
sycl::_V1::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:238
sycl::_V1::detail::backend_errc
backend_errc
Definition: backend.hpp:52
sycl::_V1::make_kernel
kernel make_kernel(const typename backend_traits< Backend >::template input_type< kernel > &BackendObject, const context &TargetContext)
Definition: backend.hpp:314
sycl::_V1::detail::BufferInterop< backend::opencl, DataT, Dimensions, AllocatorT >::ReturnType
backend_return_t< backend::opencl, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:92
sycl::_V1::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:290
device.hpp
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:11
sycl::_V1::buffer
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:37
sycl::_V1::detail::BufferInterop
Definition: backend.hpp:76
sycl::_V1::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:248
context.hpp
event.hpp
sycl::_V1::detail::get_native_buffer
auto get_native_buffer(const buffer< DataT, Dimensions, Allocator, void > &Obj) -> backend_return_t< BackendName, buffer< DataT, Dimensions, Allocator, void >>
sycl::_V1::backend_traits
Definition: backend.hpp:55
sycl::_V1::Dimensions
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:2854
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
sycl::_V1::detail::BufferInterop::ReturnType
backend_return_t< Backend, buffer< DataT, Dimensions, AllocatorT > > ReturnType
Definition: backend.hpp:78
sycl::_V1::accessor
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(accessor) accessor accessor(buffer< DataT, Dimensions, AllocatorT >) -> accessor< DataT, Dimensions, access::mode::read_write, target::device, access::placeholder::true_t >
Buffer accessor.
sycl::_V1::event
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:40
pi.hpp
cast
To cast(From value)
Definition: pi_opencl.cpp:42
backend_traits.hpp
sycl::_V1::detail::BackendInput
Definition: backend_traits.hpp:20
__SYCL_DEPRECATED
#define __SYCL_DEPRECATED(message)
Definition: defines_elementary.hpp:46
sycl::_V1::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:269
sycl::_V1::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:325
sycl::_V1::backend_input_t
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:68
export.hpp
backend_traits_level_zero.hpp
sycl::_V1::access::placeholder
placeholder
Definition: access.hpp:45
sycl::_V1::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:258
kernel_bundle.hpp
backend_traits_cuda.hpp
sycl::_V1::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
sycl::_V1::kernel_bundle
The kernel_bundle class represents collection of device images in a particular state.
Definition: kernel.hpp:29
common.hpp
sycl::_V1::backend_return_t
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:72
queue.hpp
backend_traits_hip.hpp
sycl::_V1::access::target
target
Definition: access.hpp:18
sycl::_V1::access::target::device
@ device
sycl::_V1::detail::BufferInterop< backend::opencl, DataT, Dimensions, AllocatorT >::GetNativeObjs
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:94
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:133
accessor.hpp
sycl::_V1::detail::BackendReturn
Definition: backend_traits.hpp:22
sycl::_V1::backend::opencl
@ opencl
backend_types.hpp
platform.hpp
exception.hpp
std
Definition: accessor.hpp:3230
sycl::_V1::backend_traits::input_type
typename detail::BackendInput< Backend, T >::type input_type
Definition: backend.hpp:58
sycl::_V1::detail::BufferInterop::GetNativeObjs
static ReturnType GetNativeObjs(const std::vector< pi_native_handle > &Handle)
Definition: backend.hpp:80
sycl::_V1::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:304
sycl::_V1::async_handler
std::function< void(sycl::exception_list)> async_handler
Definition: exception_list.hpp:54
buffer.hpp
backend_traits_cuda.hpp
sycl::_V1::bundle_state
bundle_state
Definition: kernel_bundle_enums.hpp:14
sycl::_V1::AccessMode
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS AccessMode
Definition: accessor.hpp:2854
sycl::_V1::errc::kernel
@ kernel
sycl::_V1::backend_traits::return_type
typename detail::BackendReturn< Backend, T >::type return_type
Definition: backend.hpp:61
sycl::_V1::context
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:41