Skip to content

Commit 29a5369

Browse files
[SYCL][L0] Adds device member to L0 make_queue input type (#6148)
* [SYCL][L0] Adds device member to L0 make_queue input type This commit adds a new `device` member to the `make_queue` input type for the L0 backend. This allows the L0 backend to correctly associate the right device with the command queue to create the PI queue from, preventing unintended and illegal behavior when the PI queue is later used for otherwise valid operations. It is currently still valid to create a SYCL queue from a native L0 command queue without associating the correct device, which will lead to the queue being associated with the first device in the supplied SYCL context. This behavior is however marked as deprecated. Note: The ABI checker test changes were generated with the checker tool, so the ones that are marked as removed are simply just moved by the tool. This is a non-breaking ABI change for the runtime library. Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
1 parent 7ed7462 commit 29a5369

File tree

17 files changed

+191
-46
lines changed

17 files changed

+191
-46
lines changed

sycl/doc/extensions/supported/sycl_ext_oneapi_backend_level_zero.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This extension provides a feature-test macro as described in the core SYCL speci
1414
|---|:---|
1515
|1|Initial extension version.
1616
|2|Added support for the make_buffer() API.
17+
|3|Added device member to backend_input_t<backend::ext_oneapi_level_zero, queue>.
1718

1819
NOTE: This extension is following SYCL 2020 backend specification. Prior API for interoperability with Level-Zero is marked
1920
as deprecated and will be removed in the next release.
@@ -108,8 +109,8 @@ struct {
108109
```
109110
</td>
110111
</tr><tr>
111-
<td>queue</td>
112-
<td><pre>ze_command_queue_handle_t</pre></td>
112+
<td rowspan="2">queue</td>
113+
<td rowspan="2"><pre>ze_command_queue_handle_t</pre></td>
113114
<td>
114115
115116
``` C++
@@ -119,6 +120,22 @@ struct {
119120
ext::oneapi::level_zero::ownership::transfer};
120121
}
121122
```
123+
124+
Deprecated as of version 3 of this specification.[^1]
125+
</td>
126+
</tr><tr>
127+
<td>
128+
129+
``` C++
130+
struct {
131+
ze_command_queue_handle_t NativeHandle;
132+
device Device;
133+
ext::oneapi::level_zero::ownership Ownership{
134+
ext::oneapi::level_zero::ownership::transfer};
135+
}
136+
```
137+
138+
Supported since version 3 of this specification.[^1]
122139
</td>
123140
</tr><tr>
124141
<td>event</td>
@@ -191,6 +208,8 @@ struct {
191208
</tr>
192209
</table>
193210
211+
[^1]: The SYCL implementation is responsible for distinguishing between the variants of <code>backend_input_t<backend::ext_oneapi_level_zero, queue></code>.
212+
194213
### 4.2 Obtaining of native Level-Zero handles from SYCL objects
195214
196215
The ```sycl::get_native<backend::ext_oneapi_level_zero>``` free-function is how a raw native Level-Zero handle can be obtained
@@ -275,7 +294,10 @@ make_queue<backend::ext_oneapi_level_zero>(
275294
const context &Context)
276295
```
277296
</td>
278-
<td>Constructs a SYCL queue instance from a Level-Zero <code>ze_command_queue_handle_t</code>. The <code>Context</code> argument must be a valid SYCL context encapsulating a Level-Zero context. The queue is attached to the first device in the passed SYCL context. 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>
297+
<td>Constructs a SYCL queue instance from a Level-Zero <code>ze_command_queue_handle_t</code>. The <code>Context</code> argument must be a valid SYCL context encapsulating a Level-Zero context. The <code>Device</code> input structure member specifies the device to create the <code>queue</code> against and must be in <code>Context</code>. 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.
298+
299+
If the deprecated variant of <code>backend_input_t<backend::ext_oneapi_level_zero, queue></code> is passed to <code>make_queue</code> the queue is attached to the first device in <code>Context</code>.
300+
</td>
279301
</tr><tr>
280302
<td>
281303

@@ -485,3 +507,4 @@ struct free_memory {
485507
|6|2021-08-30|Dmitry Vodopyanov|Updated according to SYCL 2020 reqs for extensions
486508
|7|2021-09-13|Sergey Maslov|Updated according to SYCL 2020 standard
487509
|8|2022-01-06|Artur Gainullin|Introduced make_buffer() API
510+
|9|2022-05-12|Steffen Larsen|Added device member to queue input type

sycl/include/CL/sycl/backend.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ __SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
208208
__SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
209209
const async_handler &Handler,
210210
backend Backend);
211+
__SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
212+
const context &TargetContext,
213+
const device &TargetDevice, bool KeepOwnership,
214+
const async_handler &Handler, backend Backend);
215+
// TODO: Unused. Remove when allowed.
211216
__SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
212217
const context &TargetContext, bool KeepOwnership,
213218
const async_handler &Handler, backend Backend);

sycl/include/CL/sycl/detail/backend_traits_level_zero.hpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <CL/sycl/kernel_bundle.hpp>
2525
#include <CL/sycl/queue.hpp>
2626
#include <sycl/ext/oneapi/backend/level_zero_ownership.hpp>
27+
#include <sycl/ext/oneapi/filter_selector.hpp>
2728

2829
typedef struct _ze_command_queue_handle_t *ze_command_queue_handle_t;
2930
typedef struct _ze_context_handle_t *ze_context_handle_t;
@@ -38,6 +39,9 @@ __SYCL_INLINE_NAMESPACE(cl) {
3839
namespace sycl {
3940
namespace detail {
4041

42+
// Forward declarations
43+
class device_impl;
44+
4145
// TODO the interops for context, device, event, platform and program
4246
// may be removed after removing the deprecated 'get_native()' methods
4347
// from the corresponding classes. The interop<backend, queue> specialization
@@ -130,11 +134,61 @@ template <> struct BackendReturn<backend::ext_oneapi_level_zero, event> {
130134
using type = ze_event_handle_t;
131135
};
132136

137+
struct OptionalDevice {
138+
OptionalDevice() : DeviceImpl(nullptr) {}
139+
OptionalDevice(device dev) : DeviceImpl(getSyclObjImpl(dev)) {}
140+
141+
operator device() const {
142+
if (!DeviceImpl)
143+
throw runtime_error("No device has been set.", PI_INVALID_DEVICE);
144+
return createSyclObjFromImpl<device>(DeviceImpl);
145+
}
146+
147+
OptionalDevice &operator=(OptionalDevice &Other) {
148+
DeviceImpl = Other.DeviceImpl;
149+
return *this;
150+
}
151+
OptionalDevice &operator=(device &Other) {
152+
DeviceImpl = getSyclObjImpl(Other);
153+
return *this;
154+
}
155+
156+
private:
157+
std::shared_ptr<device_impl> DeviceImpl;
158+
159+
friend bool OptionalDeviceHasDevice(const OptionalDevice &Dev);
160+
};
161+
162+
// Inspector function in the detail namespace to avoid exposing
163+
// OptionalDevice::hasDevice to user-space.
164+
inline bool OptionalDeviceHasDevice(const OptionalDevice &Dev) {
165+
return Dev.DeviceImpl != nullptr;
166+
}
167+
133168
template <> struct BackendInput<backend::ext_oneapi_level_zero, queue> {
134169
struct type {
135170
interop<backend::ext_oneapi_level_zero, queue>::type NativeHandle;
136-
ext::oneapi::level_zero::ownership Ownership{
137-
ext::oneapi::level_zero::ownership::transfer};
171+
ext::oneapi::level_zero::ownership Ownership;
172+
173+
// TODO: Change this to be device when the deprecated constructor is
174+
// removed.
175+
OptionalDevice Device;
176+
177+
type()
178+
: Ownership(ext::oneapi::level_zero::ownership::transfer), Device() {}
179+
180+
__SYCL_DEPRECATED("Use backend_input_t<backend::ext_oneapi_level_zero, "
181+
"queue> constructor with device parameter")
182+
type(interop<backend::ext_oneapi_level_zero, queue>::type nativeHandle,
183+
ext::oneapi::level_zero::ownership ownership =
184+
ext::oneapi::level_zero::ownership::transfer)
185+
: NativeHandle(nativeHandle), Ownership(ownership), Device() {}
186+
187+
type(interop<backend::ext_oneapi_level_zero, queue>::type nativeHandle,
188+
device dev,
189+
ext::oneapi::level_zero::ownership ownership =
190+
ext::oneapi::level_zero::ownership::transfer)
191+
: NativeHandle(nativeHandle), Ownership(ownership), Device(dev) {}
138192
};
139193
};
140194

sycl/include/CL/sycl/detail/pi.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@
4444
// piQueueFlush function.
4545
// 7.9 Added new context and ownership arguments to
4646
// piextMemCreateWithNativeHandle.
47+
// 8.10 Added new optional device argument to piextQueueCreateWithNativeHandle
4748
//
4849
#include "CL/cl.h"
49-
#define _PI_H_VERSION_MAJOR 7
50-
#define _PI_H_VERSION_MINOR 9
50+
#define _PI_H_VERSION_MAJOR 8
51+
#define _PI_H_VERSION_MINOR 10
5152

5253
#define _PI_STRING_HELPER(a) #a
5354
#define _PI_CONCAT(a, b) _PI_STRING_HELPER(a.b)
@@ -1158,12 +1159,15 @@ piextQueueGetNativeHandle(pi_queue queue, pi_native_handle *nativeHandle);
11581159
///
11591160
/// \param nativeHandle is the native handle to create PI queue from.
11601161
/// \param context is the PI context of the queue.
1161-
/// \param queue is the PI queue created from the native handle.
1162+
/// \param device is the PI device associated with the native device used when
1163+
/// creating the native queue. This parameter is optional but some backends
1164+
/// may fail to create the right PI queue if omitted.
11621165
/// \param pluginOwnsNativeHandle Indicates whether the created PI object
11631166
/// should take ownership of the native handle.
1167+
/// \param queue is the PI queue created from the native handle.
11641168
__SYCL_EXPORT pi_result piextQueueCreateWithNativeHandle(
1165-
pi_native_handle nativeHandle, pi_context context, pi_queue *queue,
1166-
bool pluginOwnsNativeHandle);
1169+
pi_native_handle nativeHandle, pi_context context, pi_device device,
1170+
bool pluginOwnsNativeHandle, pi_queue *queue);
11671171

11681172
//
11691173
// Memory
@@ -1823,9 +1827,9 @@ struct _pi_plugin {
18231827
// Some choices are:
18241828
// - Use of integers to keep major and minor version.
18251829
// - Keeping char* Versions.
1826-
char PiVersion[4];
1830+
char PiVersion[10];
18271831
// Plugin edits this.
1828-
char PluginVersion[4];
1832+
char PluginVersion[10];
18291833
char *Targets;
18301834
struct FunctionPointers {
18311835
#define _PI_API(api) decltype(::api) *api;

sycl/include/CL/sycl/feature_test.hpp.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ namespace sycl {
6969
#define SYCL_EXT_INTEL_MEM_CHANNEL_PROPERTY 1
7070
#define SYCL_EXT_INTEL_USM_ADDRESS_SPACES 1
7171
#define SYCL_EXT_INTEL_RUNTIME_BUFFER_LOCATION 1
72-
#define SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO 2
72+
#define SYCL_EXT_ONEAPI_BACKEND_LEVEL_ZERO 3
7373
#define SYCL_EXT_ONEAPI_USM_DEVICE_READ_ONLY 1
7474
#cmakedefine01 SYCL_BUILD_PI_CUDA
7575
#if SYCL_BUILD_PI_CUDA

sycl/include/sycl/ext/oneapi/backend/level_zero.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,13 @@ __SYCL_EXPORT context make_context(const std::vector<device> &DeviceList,
3131
__SYCL_EXPORT program make_program(const context &Context,
3232
pi_native_handle NativeHandle);
3333
#endif
34+
__SYCL_DEPRECATED("Use make_queue with device parameter")
3435
__SYCL_EXPORT queue make_queue(const context &Context,
3536
pi_native_handle InteropHandle,
3637
bool keep_ownership = false);
38+
__SYCL_EXPORT queue make_queue(const context &Context, const device &Device,
39+
pi_native_handle InteropHandle,
40+
bool keep_ownership = false);
3741
__SYCL_EXPORT event make_event(const context &Context,
3842
pi_native_handle InteropHandle,
3943
bool keep_ownership = false);
@@ -136,8 +140,11 @@ inline queue make_queue<backend::ext_oneapi_level_zero>(
136140
const backend_input_t<backend::ext_oneapi_level_zero, queue> &BackendObject,
137141
const context &TargetContext, const async_handler Handler) {
138142
(void)Handler;
143+
const device Device = detail::OptionalDeviceHasDevice(BackendObject.Device)
144+
? device{BackendObject.Device}
145+
: TargetContext.get_devices()[0];
139146
return ext::oneapi::level_zero::make_queue(
140-
TargetContext,
147+
TargetContext, Device,
141148
detail::pi::cast<pi_native_handle>(BackendObject.NativeHandle),
142149
BackendObject.Ownership == ext::oneapi::level_zero::ownership::keep);
143150
}

sycl/plugins/cuda/pi_cuda.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,8 +2443,8 @@ pi_result cuda_piextQueueGetNativeHandle(pi_queue queue,
24432443
///
24442444
/// \return TBD
24452445
pi_result cuda_piextQueueCreateWithNativeHandle(pi_native_handle, pi_context,
2446-
pi_queue *,
2447-
bool ownNativeHandle) {
2446+
pi_device, bool ownNativeHandle,
2447+
pi_queue *) {
24482448
(void)ownNativeHandle;
24492449
cl::sycl::detail::pi::die(
24502450
"Creation of PI queue from native handle not implemented");
@@ -5053,7 +5053,10 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
50535053
}
50545054

50555055
// PI interface supports higher version or the same version.
5056-
strncpy(PluginInit->PluginVersion, SupportedVersion, 4);
5056+
size_t PluginVersionSize = sizeof(PluginInit->PluginVersion);
5057+
if (strlen(SupportedVersion) >= PluginVersionSize)
5058+
return PI_INVALID_VALUE;
5059+
strncpy(PluginInit->PluginVersion, SupportedVersion, PluginVersionSize);
50575060

50585061
// Set whole function table to zero to make it easier to detect if
50595062
// functions are not set up below.

sycl/plugins/esimd_emulator/pi_esimd_emulator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ pi_result piextQueueGetNativeHandle(pi_queue, pi_native_handle *) {
10001000
}
10011001

10021002
pi_result piextQueueCreateWithNativeHandle(pi_native_handle, pi_context,
1003-
pi_queue *, bool) {
1003+
pi_device, bool, pi_queue *) {
10041004
DIE_NO_IMPLEMENTATION;
10051005
}
10061006

sycl/plugins/hip/pi_hip.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,10 +2310,12 @@ pi_result hip_piextQueueGetNativeHandle(pi_queue queue,
23102310
/// \return TBD
23112311
pi_result hip_piextQueueCreateWithNativeHandle(pi_native_handle nativeHandle,
23122312
pi_context context,
2313-
pi_queue *queue,
2314-
bool ownNativeHandle) {
2313+
pi_device device,
2314+
bool ownNativeHandle,
2315+
pi_queue *queue) {
23152316
(void)nativeHandle;
23162317
(void)context;
2318+
(void)device;
23172319
(void)queue;
23182320
(void)ownNativeHandle;
23192321
cl::sycl::detail::pi::die(
@@ -4892,7 +4894,10 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
48924894
}
48934895

48944896
// PI interface supports higher version or the same version.
4895-
strncpy(PluginInit->PluginVersion, SupportedVersion, 4);
4897+
size_t PluginVersionSize = sizeof(PluginInit->PluginVersion);
4898+
if (strlen(SupportedVersion) >= PluginVersionSize)
4899+
return PI_INVALID_VALUE;
4900+
strncpy(PluginInit->PluginVersion, SupportedVersion, PluginVersionSize);
48964901

48974902
// Set whole function table to zero to make it easier to detect if
48984903
// functions are not set up below.

sycl/plugins/level_zero/pi_level_zero.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,8 +3468,9 @@ pi_result piextQueueGetNativeHandle(pi_queue Queue,
34683468
}
34693469

34703470
pi_result piextQueueCreateWithNativeHandle(pi_native_handle NativeHandle,
3471-
pi_context Context, pi_queue *Queue,
3472-
bool OwnNativeHandle) {
3471+
pi_context Context, pi_device Device,
3472+
bool OwnNativeHandle,
3473+
pi_queue *Queue) {
34733474
PI_ASSERT(Context, PI_INVALID_CONTEXT);
34743475
PI_ASSERT(NativeHandle, PI_INVALID_VALUE);
34753476
PI_ASSERT(Queue, PI_INVALID_QUEUE);
@@ -3478,9 +3479,11 @@ pi_result piextQueueCreateWithNativeHandle(pi_native_handle NativeHandle,
34783479
// Assume this is the "0" index queue in the compute command-group.
34793480
std::vector<ze_command_queue_handle_t> ZeQueues{ZeQueue};
34803481

3481-
// Attach the queue to the "0" device.
3482-
// TODO: see if we need to let user choose the device.
3483-
pi_device Device = Context->Devices[0];
3482+
// For compatibility with older implementations we allow the device to be
3483+
// optional for now. Once the deprecated interop API is removed this can be
3484+
// changed to an assert(Device).
3485+
if (!Device)
3486+
Device = Context->Devices[0];
34843487
// TODO: see what we can do to correctly initialize PI queue for
34853488
// compute vs. copy Level-Zero queue. Currently we will send
34863489
// all commands to the "ZeQueue".

sycl/plugins/opencl/pi_opencl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,9 @@ pi_result piQueueCreate(pi_context context, pi_device device,
431431
}
432432

433433
pi_result piextQueueCreateWithNativeHandle(pi_native_handle nativeHandle,
434-
pi_context, pi_queue *piQueue,
435-
bool ownNativeHandle) {
434+
pi_context, pi_device,
435+
bool ownNativeHandle,
436+
pi_queue *piQueue) {
436437
(void)ownNativeHandle;
437438
assert(piQueue != nullptr);
438439
*piQueue = reinterpret_cast<pi_queue>(nativeHandle);
@@ -1441,7 +1442,10 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
14411442
}
14421443

14431444
// PI interface supports higher version or the same version.
1444-
strncpy(PluginInit->PluginVersion, SupportedVersion, 4);
1445+
size_t PluginVersionSize = sizeof(PluginInit->PluginVersion);
1446+
if (strlen(SupportedVersion) >= PluginVersionSize)
1447+
return PI_INVALID_VALUE;
1448+
strncpy(PluginInit->PluginVersion, SupportedVersion, PluginVersionSize);
14451449

14461450
#define _PI_CL(pi_api, ocl_api) \
14471451
(PluginInit->PiFunctionTable).pi_api = (decltype(&::pi_api))(&ocl_api);

0 commit comments

Comments
 (0)