You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[SYCL] native image handle support for LevelZero. (#8603)
New interop support for images for LevelZero. Includes make_image and
interop_handle::get_native_mem.
Tests are present in this PR.
---------
Signed-off-by: Chris Perkins <[email protected]>
Co-authored-by: Steffen Larsen <[email protected]>
Copy file name to clipboardExpand all lines: sycl/doc/extensions/supported/sycl_ext_oneapi_backend_level_zero.md
+158-34
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,7 @@ NOTE: By necessity, this specification exposes some details about the way SYCL i
17
17
|2|Added support for the make_buffer() API.
18
18
|3|Added device member to backend_input_t<backend::ext_oneapi_level_zero, queue>.
19
19
|4|Change the definition of backend_input_t and backend_return_t for the queue object, which changes the API for make_queue and get_native (when applied to queue).
20
+
|5|Added support for make_image() API.
20
21
21
22
NOTE: This extension is following SYCL 2020 backend specification. Prior API for interoperability with Level-Zero is marked
22
23
as deprecated and will be removed in the next release.
@@ -43,15 +44,15 @@ There are multiple ways in which the Level-Zero backend can be selected by the u
43
44
44
45
### 3.1 Through an environment variable
45
46
46
-
The SYCL_DEVICE_FILTER environment variable limits the SYCL runtime to use only a subset of the system's devices.
47
-
By using ```level_zero``` for backend in SYCL_DEVICE_FILTER you can select the use of Level-Zero as a SYCL backend.
47
+
The ONEAPI_DEVICE_SELECTOR environment variable limits the SYCL runtime to use only a subset of the system's devices.
48
+
By using ```level_zero``` for backend in ONEAPI_DEVICE_SELECTOR you can select the use of Level-Zero as a SYCL backend.
48
49
For further details see here: <https://github.com/intel/llvm/blob/sycl/sycl/doc/EnvironmentVariables.md>.
49
50
50
51
### 3.2 Through a programming API
51
52
52
53
There is an extension that introduces a filtering device selection to SYCL described in
Similar to how SYCL_DEVICE_FILTER applies filtering to the entire process this device selector can be used to
55
+
Similar to how SYCL_DEVICE_FILTER or ONEAPI_DEVICE_SELECTOR applies filtering to the entire process this device selector can be used to
55
56
programmatically select the Level-Zero backend.
56
57
57
58
When neither the environment variable nor the filtering device selector are used, the implementation chooses
@@ -247,6 +248,28 @@ struct {
247
248
```
248
249
</td>
249
250
</tr>
251
+
<tr>
252
+
<td>image</td>
253
+
<td>
254
+
255
+
``` C++
256
+
ze_image_handle_t
257
+
```
258
+
</td>
259
+
<td>
260
+
261
+
```C++
262
+
struct {
263
+
ze_image_handle_t ZeImageHandle;
264
+
sycl::image_channel_order ChanOrder;
265
+
sycl::image_channel_type ChanType;
266
+
sycl::range<Dimensions> Range;
267
+
ext::oneapi::level_zero::ownership Ownership{
268
+
ext::oneapi::level_zero::ownership::transfer};
269
+
}
270
+
```
271
+
</td>
272
+
</tr>
250
273
</table>
251
274
252
275
### 4.2 Obtaining of native Level-Zero handles from SYCL objects
@@ -264,7 +287,7 @@ It is currently supported for SYCL ```platform```, ```device```, ```context```,
264
287
The ```get_native(queue)``` function returns either ```ze_command_queue_handle_t``` or ```ze_command_list_handle_t``` depending on the manner in which the input argument ```queue``` had been created. Queues created with the SYCL ```queue``` constructors have a default setting for whether they use command queues or command lists. The default and how it may be changed is documented in the description for the environment variable ```SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS```. Queues created using ```make_queue()``` use either a command list or command queue depending on the input argument to ```make_queue``` and are not affected by the default for SYCL queues or the environment variable.
265
288
266
289
The ```sycl::get_native<backend::ext_oneapi_level_zero>```
267
-
free-function is not supported for SYCL ```buffer``` class. The native backend object associated with the
290
+
free-function is not supported for SYCL ```buffer```or ```image```class. The native backend object associated with the
268
291
buffer can be obtained using interop_hande class as described in the core SYCL specification section
269
292
4.10.2, "Class interop_handle".
270
293
The pointer returned by ```get_native_mem<backend::ext_oneapi_level_zero>``` method of the ```interop_handle```
@@ -299,39 +322,39 @@ an application to create a SYCL object that encapsulates a corresponding Level-Z
299
322
<td>
300
323
301
324
``` C++
302
-
make_platform<backend::ext_oneapi_level_zero>(
303
-
const backend_input_t<
304
-
backend::ext_oneapi_level_zero, platform> &)
325
+
template <backend Backend>
326
+
platform make_platform(
327
+
const backend_input_t<Backend, platform> &)
305
328
```
306
329
</td>
307
330
<td>Constructs a SYCL platform instance from a Level-Zero <code>ze_driver_handle_t</code>. The SYCL execution environment contains a fixed number of platforms that are enumerated via <code>sycl::platform::get_platforms()</code>. Calling this function does not create a new platform. Rather it merely creates a <code>sycl::platform</code> object that is a copy of one of the platforms from that enumeration.</td>
308
331
</tr><tr>
309
332
<td>
310
333
311
334
```C++
312
-
make_device<backend::ext_oneapi_level_zero>(
313
-
constbackend_input_t<
314
-
backend::ext_oneapi_level_zero, device> &)
335
+
template <backend Backend>
336
+
device make_device(
337
+
const backend_input_t<Backend, device> &)
315
338
```
316
339
</td>
317
340
<td>Constructs a SYCL device instance from a Level-Zero <code>ze_device_handle_t</code>. The SYCL execution environment for the Level Zero backend contains a fixed number of devices that are enumerated via <code>sycl::device::get_devices()</code> and a fixed number of sub-devices that are enumerated via <code>sycl::device::create_sub_devices(...)</code>. Calling this function does not create a new device. Rather it merely creates a <code>sycl::device</code> object that is a copy of one of the devices from those enumerations.</td>
318
341
</tr><tr>
319
342
<td>
320
343
321
344
``` C++
322
-
make_context<backend::ext_oneapi_level_zero>(
323
-
constbackend_input_t<
324
-
backend::ext_oneapi_level_zero, context> &)
345
+
template <backend Backend>
346
+
context make_context(
347
+
const backend_input_t<Backend, context> &)
325
348
```
326
349
</td>
327
350
<td>Constructs a SYCL context instance from a Level-Zero <code>ze_context_handle_t</code>. The context is created against the devices passed in <code>DeviceList</code> structure member. There must be at least one device given and all the devices must be from the same SYCL platform and thus from the same Level-Zero driver. The <code>Ownership</code> input structure member specifies if the SYCL runtime should take ownership of the passed native handle. The default behavior is to transfer the ownership to the SYCL runtime. See section 4.4 for details.</td>
328
351
</tr><tr>
329
352
<td>
330
353
331
354
```C++
332
-
make_queue<backend::ext_oneapi_level_zero>(
333
-
constbackend_input_t<
334
-
backend::ext_oneapi_level_zero, queue> &,
355
+
template <backend Backend>
356
+
queue make_queue(
357
+
const backend_input_t<Backend, queue> &,
335
358
const context &Context)
336
359
```
337
360
</td>
@@ -346,9 +369,9 @@ the ```compute_index``` property which is built into the command queue or comman
@@ -433,6 +468,94 @@ Construct a SYCL buffer instance from a pointer to a Level Zero memory allocatio
433
468
description above for semantics and restrictions.
434
469
The additional <code>AvailableEvent</code> argument must be a valid SYCL event. The instance of the SYCL buffer class template being constructed must wait for the SYCL event parameter to signal that the memory native handle is ready to be used.
435
470
</tr>
471
+
472
+
<tr>
473
+
<td>
474
+
475
+
```C++
476
+
template<backend Backend, int Dimensions = 1,
477
+
typename AllocrT = sycl::image_allocator>
478
+
image<Dimensions, AllocrT> make_image(
479
+
const backend_input_t<Backend,
480
+
image<Dimensions,
481
+
AllocrT>> &backendObject,
482
+
const context &targetContext);
483
+
```
484
+
</td>
485
+
<td>This API is available starting with revision 5 of this specification.
486
+
487
+
Construct a SYCL image instance from a ze_image_handle_t.
488
+
489
+
Because LevelZero has no way of getting image information from an image, it must be provided. The <code>backend_input_t</code> is a struct type like so:
490
+
``` C++
491
+
struct type {
492
+
ze_image_handle_t ZeImageHandle;
493
+
sycl::image_channel_order ChanOrder;
494
+
sycl::image_channel_type ChanType;
495
+
sycl::range<Dimensions> Range;
496
+
ext::oneapi::level_zero::ownership Ownership{
497
+
ext::oneapi::level_zero::ownership::transfer};
498
+
};
499
+
```
500
+
where the Range should be ordered (width), (width, height), or (width, height, depth) for 1D, 2D and 3D images respectively,
501
+
with those values matching the dimensions used in the `ze_image_desc` that was used to create the `ze_image_handle_t` initially.
502
+
Note that the range term ordering (width first, depth last) is true for SYCL 1.2.1 images that are supported here. But future classes like
503
+
sampled_image and unsampled_image might have a different ordering.
The image can only be used on the single device where it was created. This limitation may be relaxed in the future.
534
+
The <code>Context</code> argument must be a valid SYCL context encapsulating a Level-Zero context, and the Level-Zero image must have been created on the same context. The created SYCL image can only be accessed from kernels that are submitted to a queue using this same context.
535
+
The <code>Ownership</code> input structure member specifies if the SYCL runtime should take ownership of the passed native handle. The default behavior is to transfer the ownership to the SYCL runtime. See section 4.4 for details. If the behavior is "transfer" then the SYCL runtime is going to free the input Level-Zero memory allocation, meaning the memory will be freed when the ~image destructor fires. When using "transfer" the ~image destructor may not need to block. If the behavior is "keep", then the memory will not be freed by the ~image destructor, and the ~image destructor blocks until all work in the queues on the image have been completed. When using "keep" it is the responsibility of the caller to free the memory appropriately.
<td>This API is available starting with revision 5 of this specification.
553
+
554
+
Construct a SYCL image instance from a pointer to a Level Zero memory allocation. Please refer to <code>make_image</code>
555
+
description above for semantics and restrictions.
556
+
The additional <code>AvailableEvent</code> argument must be a valid SYCL event. The instance of the SYCL image class template being constructed must wait for the SYCL event parameter to signal that the memory native handle is ready to be used.
557
+
</td>
558
+
</tr>
436
559
</table>
437
560
438
561
NOTE: We shall consider adding other interoperability as needed, if possible.
@@ -509,4 +632,5 @@ The behavior of the SYCL buffer destructor depends on the Ownership flag. As wit
509
632
|8|2022-01-06|Artur Gainullin|Introduced make_buffer() API
510
633
|9|2022-05-12|Steffen Larsen|Added device member to queue input type
511
634
|10|2022-08-18|Sergey Maslov|Moved free_memory device info query to be sycl_ext_intel_device_info extension
512
-
|10|2023-03-14|Rajiv Deodhar|Added support for Level Zero immediate command lists
635
+
|11|2023-03-14|Rajiv Deodhar|Added support for Level Zero immediate command lists
636
+
|12|2023-04-06|Chris Perkins|Introduced make_image() API
0 commit comments