DPC++ Runtime
Runtime libraries for oneAPI DPC++
level_zero.hpp
Go to the documentation of this file.
1 //==--------- level_zero.hpp - SYCL Level-Zero backend ---------------------==//
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/async_handler.hpp> // for async_han...
12 #include <sycl/backend.hpp> // for backend_i...
13 #include <sycl/backend_types.hpp> // for backend
14 #include <sycl/buffer.hpp> // for buffer_al...
15 #include <sycl/context.hpp> // for context
16 #include <sycl/detail/backend_traits.hpp> // for interop
17 #include <sycl/detail/backend_traits_level_zero.hpp> // for ze_comman...
18 #include <sycl/detail/defines_elementary.hpp> // for __SYCL_DE...
19 #include <sycl/detail/export.hpp> // for __SYCL_EX...
20 #include <sycl/detail/impl_utils.hpp> // for createSyc...
21 #include <sycl/detail/pi.h> // for pi_native...
22 #include <sycl/detail/pi.hpp> // for cast
23 #include <sycl/device.hpp> // for device
24 #include <sycl/event.hpp> // for event
26 #include <sycl/ext/oneapi/backend/level_zero_ownership.hpp> // for ownership
27 #include <sycl/image.hpp> // for image
28 #include <sycl/kernel.hpp> // for kernel
29 #include <sycl/kernel_bundle.hpp> // for kernel_bu...
30 #include <sycl/kernel_bundle_enums.hpp> // for bundle_state
31 #include <sycl/platform.hpp> // for platform
32 #include <sycl/properties/image_properties.hpp> // for image
33 #include <sycl/property_list.hpp> // for property_...
34 #include <sycl/queue.hpp> // for queue
35 
36 #include <memory> // for shared_ptr
37 #include <stdint.h> // for int32_t
38 #include <type_traits> // for enable_if_t
39 #include <variant> // for get_if
40 #include <vector> // for vector
41 
42 namespace sycl {
43 inline namespace _V1 {
44 namespace ext::oneapi::level_zero::detail {
45 __SYCL_EXPORT device make_device(const platform &Platform,
46  pi_native_handle NativeHandle);
47 } // namespace ext::oneapi::level_zero::detail
48 
49 // Specialization of sycl::make_context for Level-Zero backend.
50 template <>
51 inline context make_context<backend::ext_oneapi_level_zero>(
53  &BackendObject,
54  const async_handler &Handler) {
55 
56  const std::vector<device> &DeviceList = BackendObject.DeviceList;
57  pi_native_handle NativeHandle =
58  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle);
59  bool KeepOwnership =
60  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep;
61 
62  return sycl::detail::make_context(NativeHandle, Handler,
64  KeepOwnership, DeviceList);
65 }
66 
67 namespace detail {
68 inline std::optional<sycl::device> find_matching_descendent_device(
69  sycl::device d,
71  &BackendObject) {
72  if (get_native<backend::ext_oneapi_level_zero>(d) == BackendObject)
73  return d;
74  std::vector<info::partition_property> partition_props =
75  d.get_info<info::device::partition_properties>();
76 
77  for (auto pp : partition_props) {
79  auto sub_devices = d.create_sub_devices<
82  for (auto sub_dev : sub_devices) {
83  if (auto maybe_device =
84  find_matching_descendent_device(sub_dev, BackendObject))
85  return maybe_device;
86  }
87  }
88 
89  assert(false && "Unexpected partitioning scheme for a Level-Zero device!");
90  }
91 
92  return {};
93 }
94 } // namespace detail
95 
96 // Specialization of sycl::make_device for Level-Zero backend.
97 // Level-Zero backend specification says:
98 //
99 // > The SYCL execution environment for the Level Zero backend contains a fixed
100 // > number of devices that are enumerated via sycl::device::get_devices() and
101 // > a fixed number of sub-devices that are enumerated via
102 // > sycl::device::create_sub_devices(...). Calling this function does not
103 // > create a new device. Rather it merely creates a sycl::device object that
104 // > is a copy of one of the devices from those enumerations.
105 //
106 // Per SYCL 2020 specification, device and it's copy should be equally
107 // comparable and its hashes must be equal. As such, we cannot simply create a
108 // new `detail::device_impl` and then a `sycl::device` out of it and have to
109 // iterate over the existing device hierarchy and make a copy.
110 template <>
111 inline device make_device<backend::ext_oneapi_level_zero>(
113  &BackendObject) {
114  for (auto p : platform::get_platforms()) {
115  if (p.get_backend() != backend::ext_oneapi_level_zero)
116  continue;
117 
118  for (auto d : p.get_devices()) {
119  if (auto maybe_device = find_matching_descendent_device(d, BackendObject))
120  return *maybe_device;
121  }
122  }
123 
125  "Native device isn't exposed to SYCL.");
126 }
127 
128 // Specialization of sycl::make_queue for Level-Zero backend.
129 template <>
130 inline queue make_queue<backend::ext_oneapi_level_zero>(
132  const context &TargetContext, const async_handler Handler) {
133  const device Device = device{BackendObject.Device};
134  bool IsImmCmdList = std::holds_alternative<ze_command_list_handle_t>(
135  BackendObject.NativeHandle);
136  pi_native_handle Handle = IsImmCmdList
137  ? reinterpret_cast<pi_native_handle>(
138  *(std::get_if<ze_command_list_handle_t>(
139  &BackendObject.NativeHandle)))
140  : reinterpret_cast<pi_native_handle>(
141  *(std::get_if<ze_command_queue_handle_t>(
142  &BackendObject.NativeHandle)));
143 
145  Handle, IsImmCmdList, TargetContext, &Device,
146  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
147  BackendObject.Properties, Handler, backend::ext_oneapi_level_zero);
148 }
149 
150 // Specialization of sycl::get_native for Level-Zero backend.
151 template <>
152 inline auto get_native<backend::ext_oneapi_level_zero, queue>(const queue &Obj)
154  int32_t IsImmCmdList;
155  pi_native_handle Handle = Obj.getNative(IsImmCmdList);
156  return IsImmCmdList
159  queue>{reinterpret_cast<ze_command_list_handle_t>(Handle)}
161  reinterpret_cast<ze_command_queue_handle_t>(Handle)};
162 }
163 
164 // Specialization of sycl::make_event for Level-Zero backend.
165 template <>
166 inline event make_event<backend::ext_oneapi_level_zero>(
168  const context &TargetContext) {
170  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
171  TargetContext,
172  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
174 }
175 
176 // Specialization of sycl::make_kernel_bundle for Level-Zero backend.
177 template <>
178 inline kernel_bundle<bundle_state::executable>
179 make_kernel_bundle<backend::ext_oneapi_level_zero, bundle_state::executable>(
181  kernel_bundle<bundle_state::executable>>
182  &BackendObject,
183  const context &TargetContext) {
184  std::shared_ptr<detail::kernel_bundle_impl> KBImpl =
186  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
187  TargetContext,
188  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
190  return detail::createSyclObjFromImpl<kernel_bundle<bundle_state::executable>>(
191  KBImpl);
192 }
193 
194 // Specialization of sycl::make_kernel for Level-Zero backend.
195 template <>
196 inline kernel make_kernel<backend::ext_oneapi_level_zero>(
198  &BackendObject,
199  const context &TargetContext) {
200  return detail::make_kernel(
201  TargetContext, BackendObject.KernelBundle,
202  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
203  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
205 }
206 
207 // Specialization of sycl::make_buffer with event for Level-Zero backend.
208 template <backend Backend, typename T, int Dimensions = 1,
209  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
210 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
211  buffer<T, Dimensions, AllocatorT>>
214  buffer<T, Dimensions, AllocatorT>> &BackendObject,
215  const context &TargetContext, event AvailableEvent) {
216  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
217  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
218  TargetContext, AvailableEvent,
219  !(BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep));
220 }
221 
222 // Specialization of sycl::make_buffer for Level-Zero backend.
223 template <backend Backend, typename T, int Dimensions = 1,
224  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
225 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
226  buffer<T, Dimensions, AllocatorT>>
229  buffer<T, Dimensions, AllocatorT>> &BackendObject,
230  const context &TargetContext) {
231  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
232  detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
233  TargetContext, event{},
234  !(BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep));
235 }
236 
237 // Specialization of sycl::make_image for Level-Zero backend.
238 template <backend Backend, int Dimensions = 1,
239  typename AllocatorT = image_allocator>
240 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
241  image<Dimensions, AllocatorT>>
243  &BackendObject,
244  const context &TargetContext, event AvailableEvent) {
245 
246  bool OwnNativeHandle =
247  (BackendObject.Ownership == ext::oneapi::level_zero::ownership::transfer);
248 
250  detail::pi::cast<pi_native_handle>(BackendObject.ZeImageHandle),
251  TargetContext, AvailableEvent, BackendObject.ChanOrder,
252  BackendObject.ChanType, OwnNativeHandle, BackendObject.Range);
253 }
254 
255 namespace __SYCL2020_DEPRECATED("use 'ext::oneapi::level_zero' instead")
256  level_zero {
257 using namespace ext::oneapi::level_zero;
258 }
259 
260 } // namespace _V1
261 } // namespace sycl
struct _ze_command_queue_handle_t * ze_command_queue_handle_t
struct _ze_command_list_handle_t * ze_command_list_handle_t
Defines a shared array that can be used by kernels in queues.
Definition: buffer.hpp:173
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
std::vector< device > create_sub_devices(size_t ComputeUnits) const
Partition device into sub devices.
Definition: device.cpp:82
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Definition: device.hpp:215
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:449
Provides an abstraction of a SYCL kernel.
Definition: kernel.hpp:71
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:99
static std::vector< platform > get_platforms()
Returns all available SYCL platforms in the system.
Definition: platform.cpp:47
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:110
kernel make_kernel(pi_native_handle NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:299
std::optional< sycl::device > find_matching_descendent_device(sycl::device d, const backend_input_t< backend::ext_oneapi_level_zero, device > &BackendObject)
Definition: level_zero.hpp:68
context make_context(pi_native_handle NativeHandle, const async_handler &Handler, backend Backend, bool KeepOwnership, const std::vector< device > &DeviceList={})
Definition: backend.cpp:92
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:111
event make_event(pi_native_handle NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:145
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:251
device make_device(const platform &Platform, pi_native_handle NativeHandle)
Definition: level_zero.cpp:20
class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
signed char __SYCL2020_DEPRECATED
Definition: aliases.hpp:94
typename backend_traits< Backend >::template return_type< SyclType > backend_return_t
Definition: backend.hpp:81
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:389
std::uint8_t instead
Definition: aliases.hpp:93
std::function< void(sycl::exception_list)> async_handler
detail::aligned_allocator< byte > image_allocator
Definition: image.hpp:109
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:64
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:376
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:77
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:256
C++ wrapper of extern "C" PI interfaces.