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/ur.hpp> // for cast
22 #include <sycl/device.hpp> // for device
23 #include <sycl/event.hpp> // for event
25 #include <sycl/ext/oneapi/backend/level_zero_ownership.hpp> // for ownership
26 #include <sycl/image.hpp> // for image
27 #include <sycl/kernel.hpp> // for kernel
28 #include <sycl/kernel_bundle.hpp> // for kernel_bu...
29 #include <sycl/kernel_bundle_enums.hpp> // for bundle_state
30 #include <sycl/platform.hpp> // for platform
31 #include <sycl/properties/image_properties.hpp> // for image
32 #include <sycl/property_list.hpp> // for property_...
33 #include <sycl/queue.hpp> // for queue
34 
35 #include <memory> // for shared_ptr
36 #include <stdint.h> // for int32_t
37 #include <type_traits> // for enable_if_t
38 #include <variant> // for get_if
39 #include <vector> // for vector
40 
41 namespace sycl {
42 inline namespace _V1 {
43 namespace ext::oneapi::level_zero::detail {
44 __SYCL_EXPORT device make_device(const platform &Platform,
45  ur_native_handle_t NativeHandle);
46 } // namespace ext::oneapi::level_zero::detail
47 
48 // Specialization of sycl::make_context for Level-Zero backend.
49 template <>
50 inline context make_context<backend::ext_oneapi_level_zero>(
52  &BackendObject,
53  const async_handler &Handler) {
54  const std::vector<device> &DeviceList = BackendObject.DeviceList;
55  ur_native_handle_t NativeHandle =
56  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle);
57  bool KeepOwnership =
58  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep;
59 
60  return sycl::detail::make_context(NativeHandle, Handler,
62  KeepOwnership, DeviceList);
63 }
64 
65 namespace detail {
66 inline std::optional<sycl::device> find_matching_descendent_device(
67  sycl::device d,
69  &BackendObject) {
70  if (get_native<backend::ext_oneapi_level_zero>(d) == BackendObject)
71  return d;
72  std::vector<info::partition_property> partition_props =
73  d.get_info<info::device::partition_properties>();
74 
75  for (auto pp : partition_props) {
77  auto sub_devices = d.create_sub_devices<
80  for (auto &sub_dev : sub_devices) {
81  if (auto maybe_device =
82  find_matching_descendent_device(sub_dev, BackendObject))
83  return maybe_device;
84  }
85  }
86 
87  assert(false && "Unexpected partitioning scheme for a Level-Zero device!");
88  }
89 
90  return {};
91 }
92 } // namespace detail
93 
94 // Specialization of sycl::make_device for Level-Zero backend.
95 // Level-Zero backend specification says:
96 //
97 // > The SYCL execution environment for the Level Zero backend contains a fixed
98 // > number of devices that are enumerated via sycl::device::get_devices() and
99 // > a fixed number of sub-devices that are enumerated via
100 // > sycl::device::create_sub_devices(...). Calling this function does not
101 // > create a new device. Rather it merely creates a sycl::device object that
102 // > is a copy of one of the devices from those enumerations.
103 //
104 // Per SYCL 2020 specification, device and it's copy should be equally
105 // comparable and its hashes must be equal. As such, we cannot simply create a
106 // new `detail::device_impl` and then a `sycl::device` out of it and have to
107 // iterate over the existing device hierarchy and make a copy.
108 template <>
109 inline device make_device<backend::ext_oneapi_level_zero>(
111  &BackendObject) {
112  for (auto &p : platform::get_platforms()) {
113  if (p.get_backend() != backend::ext_oneapi_level_zero)
114  continue;
115 
116  for (auto &d : p.get_devices()) {
117  if (auto maybe_device = find_matching_descendent_device(d, BackendObject))
118  return *maybe_device;
119  }
120  }
121 
123  "Native device isn't exposed to SYCL.");
124 }
125 
126 // Specialization of sycl::make_queue for Level-Zero backend.
127 template <>
128 inline queue make_queue<backend::ext_oneapi_level_zero>(
130  const context &TargetContext, const async_handler Handler) {
131  const device Device = device{BackendObject.Device};
132  bool IsImmCmdList = std::holds_alternative<ze_command_list_handle_t>(
133  BackendObject.NativeHandle);
134  ur_native_handle_t Handle =
135  IsImmCmdList ? reinterpret_cast<ur_native_handle_t>(
136  *(std::get_if<ze_command_list_handle_t>(
137  &BackendObject.NativeHandle)))
138  : reinterpret_cast<ur_native_handle_t>(
139  *(std::get_if<ze_command_queue_handle_t>(
140  &BackendObject.NativeHandle)));
141 
143  Handle, IsImmCmdList, TargetContext, &Device,
144  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
145  BackendObject.Properties, Handler, backend::ext_oneapi_level_zero);
146 }
147 
148 // Specialization of sycl::get_native for Level-Zero backend.
149 template <>
150 inline auto get_native<backend::ext_oneapi_level_zero, queue>(const queue &Obj)
152  int32_t IsImmCmdList;
153  ur_native_handle_t Handle = Obj.getNative(IsImmCmdList);
154  return IsImmCmdList
157  queue>{reinterpret_cast<ze_command_list_handle_t>(Handle)}
159  reinterpret_cast<ze_command_queue_handle_t>(Handle)};
160 }
161 
162 // Specialization of sycl::make_event for Level-Zero backend.
163 template <>
164 inline event make_event<backend::ext_oneapi_level_zero>(
166  const context &TargetContext) {
168  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle),
169  TargetContext,
170  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
172 }
173 
174 // Specialization of sycl::make_kernel_bundle for Level-Zero backend.
175 template <>
176 inline kernel_bundle<bundle_state::executable>
177 make_kernel_bundle<backend::ext_oneapi_level_zero, bundle_state::executable>(
179  kernel_bundle<bundle_state::executable>>
180  &BackendObject,
181  const context &TargetContext) {
182  std::shared_ptr<detail::kernel_bundle_impl> KBImpl =
184  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle),
185  TargetContext,
186  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
188  return detail::createSyclObjFromImpl<kernel_bundle<bundle_state::executable>>(
189  KBImpl);
190 }
191 
192 // Specialization of sycl::make_kernel for Level-Zero backend.
193 template <>
194 inline kernel make_kernel<backend::ext_oneapi_level_zero>(
196  &BackendObject,
197  const context &TargetContext) {
198  return detail::make_kernel(
199  TargetContext, BackendObject.KernelBundle,
200  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle),
201  BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep,
203 }
204 
205 // Specialization of sycl::make_buffer with event for Level-Zero backend.
206 template <backend Backend, typename T, int Dimensions = 1,
207  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
208 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
209  buffer<T, Dimensions, AllocatorT>>
212  buffer<T, Dimensions, AllocatorT>> &BackendObject,
213  const context &TargetContext, event AvailableEvent) {
214  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
215  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle),
216  TargetContext, AvailableEvent,
217  !(BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep));
218 }
219 
220 // Specialization of sycl::make_buffer for Level-Zero backend.
221 template <backend Backend, typename T, int Dimensions = 1,
222  typename AllocatorT = buffer_allocator<std::remove_const_t<T>>>
223 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
224  buffer<T, Dimensions, AllocatorT>>
227  buffer<T, Dimensions, AllocatorT>> &BackendObject,
228  const context &TargetContext) {
229  return detail::make_buffer_helper<T, Dimensions, AllocatorT>(
230  detail::ur::cast<ur_native_handle_t>(BackendObject.NativeHandle),
231  TargetContext, event{},
232  !(BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep));
233 }
234 
235 // Specialization of sycl::make_image for Level-Zero backend.
236 template <backend Backend, int Dimensions = 1,
237  typename AllocatorT = image_allocator>
238 std::enable_if_t<Backend == backend::ext_oneapi_level_zero,
239  image<Dimensions, AllocatorT>>
241  &BackendObject,
242  const context &TargetContext, event AvailableEvent) {
243 
244  bool OwnNativeHandle =
245  (BackendObject.Ownership == ext::oneapi::level_zero::ownership::transfer);
246 
248  detail::ur::cast<ur_native_handle_t>(BackendObject.ZeImageHandle),
249  TargetContext, AvailableEvent, BackendObject.ChanOrder,
250  BackendObject.ChanType, OwnNativeHandle, BackendObject.Range);
251 }
252 
253 namespace __SYCL2020_DEPRECATED("use 'ext::oneapi::level_zero' instead")
254  level_zero {
255 using namespace ext::oneapi::level_zero;
256 }
257 
258 } // namespace _V1
259 } // 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:84
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:51
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:110
queue make_queue(ur_native_handle_t 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:116
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:66
context make_context(ur_native_handle_t NativeHandle, const async_handler &Handler, backend Backend, bool KeepOwnership, const std::vector< device > &DeviceList={})
Definition: backend.cpp:94
std::shared_ptr< detail::kernel_bundle_impl > make_kernel_bundle(ur_native_handle_t NativeHandle, const context &TargetContext, bundle_state State, backend Backend)
Definition: backend.cpp:303
event make_event(ur_native_handle_t NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:161
kernel make_kernel(ur_native_handle_t NativeHandle, const context &TargetContext, backend Backend)
Definition: backend.cpp:354
device make_device(const platform &Platform, ur_native_handle_t 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: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:400
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:65
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:387
typename backend_traits< Backend >::template input_type< SyclType > backend_input_t
Definition: backend.hpp:83
Definition: access.hpp:18
C++ utilities for Unified Runtime integration.