12
12
// / \ingroup sycl_pi_level_zero
13
13
14
14
#include " pi_level_zero.hpp"
15
+ #include < algorithm>
15
16
#include < cstdarg>
16
17
#include < cstdio>
17
18
#include < cstring>
@@ -219,9 +220,13 @@ _pi_context::getFreeSlotInExistingOrNewPool(ze_event_pool_handle_t &ZePool,
219
220
ZeEventPoolDesc.count = MaxNumEventsPerPool;
220
221
ZeEventPoolDesc.flags = ZE_EVENT_POOL_FLAG_KERNEL_TIMESTAMP;
221
222
222
- ze_device_handle_t ZeDevice = Device->ZeDevice ;
223
- if (ze_result_t ZeRes = zeEventPoolCreate (ZeContext, &ZeEventPoolDesc, 1 ,
224
- &ZeDevice, &ZeEventPool))
223
+ std::vector<ze_device_handle_t > ZeDevices;
224
+ std::for_each (Devices.begin (), Devices.end (),
225
+ [&](pi_device &D) { ZeDevices.push_back (D->ZeDevice ); });
226
+
227
+ if (ze_result_t ZeRes =
228
+ zeEventPoolCreate (ZeContext, &ZeEventPoolDesc, ZeDevices.size (),
229
+ &ZeDevices[0 ], &ZeEventPool))
225
230
return ZeRes;
226
231
NumEventsAvailableInEventPool[ZeEventPool] = MaxNumEventsPerPool - 1 ;
227
232
NumEventsLiveInEventPool[ZeEventPool] = MaxNumEventsPerPool;
@@ -408,9 +413,9 @@ _pi_queue::resetCommandListFenceEntry(ze_command_list_handle_t ZeCommandList,
408
413
ZE_CALL (zeFenceReset (this ->ZeCommandListFenceMap [ZeCommandList]));
409
414
ZE_CALL (zeCommandListReset (ZeCommandList));
410
415
if (MakeAvailable) {
411
- this ->Context -> Device ->ZeCommandListCacheMutex .lock ();
412
- this ->Context -> Device ->ZeCommandListCache .push_back (ZeCommandList);
413
- this ->Context -> Device ->ZeCommandListCacheMutex .unlock ();
416
+ this ->Device ->ZeCommandListCacheMutex .lock ();
417
+ this ->Device ->ZeCommandListCache .push_back (ZeCommandList);
418
+ this ->Device ->ZeCommandListCacheMutex .unlock ();
414
419
}
415
420
416
421
return PI_SUCCESS;
@@ -433,7 +438,7 @@ _pi_device::getAvailableCommandList(pi_queue Queue,
433
438
434
439
// Initally, we need to check if a command list has already been created
435
440
// on this device that is available for use. If so, then reuse that
436
- // L0 Command List and Fence for this PI call.
441
+ // Level-Zero Command List and Fence for this PI call.
437
442
if (Queue->Device ->ZeCommandListCache .size () > 0 ) {
438
443
Queue->Device ->ZeCommandListCacheMutex .lock ();
439
444
*ZeCommandList = Queue->Device ->ZeCommandListCache .front ();
@@ -1402,15 +1407,14 @@ pi_result piContextCreate(const pi_context_properties *Properties,
1402
1407
const void *PrivateInfo, size_t CB,
1403
1408
void *UserData),
1404
1409
void *UserData, pi_context *RetContext) {
1405
- if (NumDevices != 1 || !Devices) {
1406
- zePrint (" piCreateContext: context should have exactly one Device\n " );
1410
+ if (!Devices) {
1407
1411
return PI_INVALID_VALUE;
1408
1412
}
1409
1413
1410
1414
assert (RetContext);
1411
1415
1412
1416
try {
1413
- *RetContext = new _pi_context (* Devices);
1417
+ *RetContext = new _pi_context (NumDevices, Devices);
1414
1418
} catch (const std::bad_alloc &) {
1415
1419
return PI_OUT_OF_HOST_MEMORY;
1416
1420
} catch (...) {
@@ -1444,9 +1448,10 @@ pi_result piContextGetInfo(pi_context Context, pi_context_info ParamName,
1444
1448
ReturnHelper ReturnValue (ParamValueSize, ParamValue, ParamValueSizeRet);
1445
1449
switch (ParamName) {
1446
1450
case PI_CONTEXT_INFO_DEVICES:
1447
- return ReturnValue (Context->Device );
1451
+ return getInfoArray (Context->Devices .size (), ParamValueSize, ParamValue,
1452
+ ParamValueSizeRet, &Context->Devices [0 ]);
1448
1453
case PI_CONTEXT_INFO_NUM_DEVICES:
1449
- return ReturnValue (pi_uint32{ 1 } );
1454
+ return ReturnValue (pi_uint32 (Context-> Devices . size ()) );
1450
1455
case PI_CONTEXT_INFO_REFERENCE_COUNT:
1451
1456
return ReturnValue (pi_uint32{Context->RefCount });
1452
1457
default :
@@ -1521,7 +1526,8 @@ pi_result piQueueCreate(pi_context Context, pi_device Device,
1521
1526
if (!Context) {
1522
1527
return PI_INVALID_CONTEXT;
1523
1528
}
1524
- if (Context->Device != Device) {
1529
+ if (std::find (Context->Devices .begin (), Context->Devices .end (), Device) ==
1530
+ Context->Devices .end ()) {
1525
1531
return PI_INVALID_DEVICE;
1526
1532
}
1527
1533
@@ -1628,7 +1634,11 @@ pi_result piextQueueCreateWithNativeHandle(pi_native_handle NativeHandle,
1628
1634
assert (Queue);
1629
1635
1630
1636
auto ZeQueue = pi_cast<ze_command_queue_handle_t >(NativeHandle);
1631
- *Queue = new _pi_queue (ZeQueue, Context, Context->Device );
1637
+
1638
+ // Attach the queue to the "0" device.
1639
+ // TODO: see if we need to let user choose the device.
1640
+ pi_device Device = Context->Devices [0 ];
1641
+ *Queue = new _pi_queue (ZeQueue, Context, Device);
1632
1642
return PI_SUCCESS;
1633
1643
}
1634
1644
@@ -1641,14 +1651,24 @@ pi_result piMemBufferCreate(pi_context Context, pi_mem_flags Flags, size_t Size,
1641
1651
assert (RetMem);
1642
1652
1643
1653
void *Ptr ;
1644
- ze_device_handle_t ZeDevice = Context->Device ->ZeDevice ;
1645
1654
1646
- ze_device_mem_alloc_desc_t ZeDesc = {};
1647
- ZeDesc.flags = 0 ;
1648
- ZeDesc.ordinal = 0 ;
1649
- ZE_CALL (zeMemAllocDevice (Context->ZeContext , &ZeDesc, Size ,
1650
- 1 , // TODO: alignment
1651
- ZeDevice, &Ptr ));
1655
+ ze_device_mem_alloc_desc_t ZeDeviceMemDesc = {};
1656
+ ZeDeviceMemDesc.flags = 0 ;
1657
+ ZeDeviceMemDesc.ordinal = 0 ;
1658
+
1659
+ if (Context->Devices .size () == 1 ) {
1660
+ ZE_CALL (zeMemAllocDevice (Context->ZeContext , &ZeDeviceMemDesc, Size ,
1661
+ 1 , // TODO: alignment
1662
+ Context->Devices [0 ]->ZeDevice , &Ptr ));
1663
+ } else {
1664
+ ze_host_mem_alloc_desc_t ZeHostMemDesc = {};
1665
+ ZeHostMemDesc.flags = 0 ;
1666
+ ZE_CALL (zeMemAllocShared (Context->ZeContext , &ZeDeviceMemDesc,
1667
+ &ZeHostMemDesc, Size ,
1668
+ 1 , // TODO: alignment
1669
+ nullptr , // not bound to any device
1670
+ &Ptr ));
1671
+ }
1652
1672
1653
1673
if ((Flags & PI_MEM_FLAGS_HOST_PTR_USE) != 0 ||
1654
1674
(Flags & PI_MEM_FLAGS_HOST_PTR_COPY) != 0 ) {
@@ -1837,9 +1857,14 @@ pi_result piMemImageCreate(pi_context Context, pi_mem_flags Flags,
1837
1857
ZeImageDesc.arraylevels = pi_cast<uint32_t >(ImageDesc->image_array_size );
1838
1858
ZeImageDesc.miplevels = ImageDesc->num_mip_levels ;
1839
1859
1860
+ // Have the "0" device in context to own the image. Rely on Level-Zero
1861
+ // drivers to perform migration as necessary for sharing it across multiple
1862
+ // devices in the context.
1863
+ //
1864
+ pi_device Device = Context->Devices [0 ];
1840
1865
ze_image_handle_t ZeHImage;
1841
- ZE_CALL (zeImageCreate (Context->ZeContext , Context-> Device ->ZeDevice ,
1842
- &ZeImageDesc, & ZeHImage));
1866
+ ZE_CALL (zeImageCreate (Context->ZeContext , Device->ZeDevice , &ZeImageDesc ,
1867
+ &ZeHImage));
1843
1868
1844
1869
auto HostPtrOrNull =
1845
1870
(Flags & PI_MEM_FLAGS_HOST_PTR_USE) ? pi_cast<char *>(HostPtr) : nullptr ;
@@ -1926,7 +1951,7 @@ pi_result piProgramCreateWithBinary(pi_context Context, pi_uint32 NumDevices,
1926
1951
*BinaryStatus = PI_INVALID_VALUE;
1927
1952
return PI_INVALID_VALUE;
1928
1953
}
1929
- if (DeviceList[0 ] != Context->Device )
1954
+ if (DeviceList[0 ] != Context->Devices [ 0 ] )
1930
1955
return PI_INVALID_DEVICE;
1931
1956
1932
1957
size_t Length = Lengths[0 ];
@@ -1975,10 +2000,11 @@ pi_result piProgramGetInfo(pi_program Program, pi_program_info ParamName,
1975
2000
case PI_PROGRAM_INFO_REFERENCE_COUNT:
1976
2001
return ReturnValue (pi_uint32{Program->RefCount });
1977
2002
case PI_PROGRAM_INFO_NUM_DEVICES:
1978
- // Level Zero Module is always for a single device .
2003
+ // TODO: return true number of devices this program exists for .
1979
2004
return ReturnValue (pi_uint32{1 });
1980
2005
case PI_PROGRAM_INFO_DEVICES:
1981
- return ReturnValue (Program->Context ->Device );
2006
+ // TODO: return all devices this program exists for.
2007
+ return ReturnValue (Program->Context ->Devices [0 ]);
1982
2008
case PI_PROGRAM_INFO_BINARY_SIZES: {
1983
2009
size_t SzBinary;
1984
2010
if (Program->State == _pi_program::IL ||
@@ -2105,9 +2131,10 @@ pi_result piProgramLink(pi_context Context, pi_uint32 NumDevices,
2105
2131
void (*PFnNotify)(pi_program Program, void *UserData),
2106
2132
void *UserData, pi_program *RetProgram) {
2107
2133
2108
- // We only support one device with Level Zero.
2134
+ // We only support one device with Level Zero currently.
2135
+ pi_device Device = Context->Devices [0 ];
2109
2136
assert (NumDevices == 1 );
2110
- assert (DeviceList && DeviceList[0 ] == Context-> Device );
2137
+ assert (DeviceList && DeviceList[0 ] == Device);
2111
2138
assert (!PFnNotify && !UserData);
2112
2139
2113
2140
// Validate input parameters.
@@ -2170,9 +2197,8 @@ pi_result piProgramLink(pi_context Context, pi_uint32 NumDevices,
2170
2197
// only export symbols.
2171
2198
Guard.unlock ();
2172
2199
ze_module_handle_t ZeModule;
2173
- pi_result res =
2174
- copyModule (Context->ZeContext , Context->Device ->ZeDevice ,
2175
- Input->ZeModule , &ZeModule);
2200
+ pi_result res = copyModule (Context->ZeContext , Device->ZeDevice ,
2201
+ Input->ZeModule , &ZeModule);
2176
2202
if (res != PI_SUCCESS) {
2177
2203
return res;
2178
2204
}
@@ -2270,7 +2296,9 @@ static pi_result compileOrBuild(pi_program Program, pi_uint32 NumDevices,
2270
2296
if ((NumDevices && !DeviceList) || (!NumDevices && DeviceList))
2271
2297
return PI_INVALID_VALUE;
2272
2298
2273
- // We only support one device with Level Zero.
2299
+ // We only support build to one device with Level Zero now.
2300
+ // TODO: we should eventually build to the possibly multiple root
2301
+ // devices in the context.
2274
2302
assert (NumDevices == 1 && DeviceList);
2275
2303
2276
2304
// We should have either IL or native device code.
@@ -2307,7 +2335,7 @@ static pi_result compileOrBuild(pi_program Program, pi_uint32 NumDevices,
2307
2335
ZeModuleDesc.pBuildFlags = Options;
2308
2336
ZeModuleDesc.pConstants = &ZeSpecConstants;
2309
2337
2310
- ze_device_handle_t ZeDevice = Program-> Context -> Device ->ZeDevice ;
2338
+ ze_device_handle_t ZeDevice = DeviceList[ 0 ] ->ZeDevice ;
2311
2339
ze_context_handle_t ZeContext = Program->Context ->ZeContext ;
2312
2340
ze_module_handle_t ZeModule;
2313
2341
ze_module_build_log_handle_t ZeBuildLog;
@@ -2905,7 +2933,8 @@ pi_result piEventCreate(pi_context Context, pi_event *RetEvent) {
2905
2933
ze_event_handle_t ZeEvent;
2906
2934
ze_event_desc_t ZeEventDesc = {};
2907
2935
// We have to set the SIGNAL & WAIT flags as HOST scope because the
2908
- // L0 plugin implementation waits for the events to complete on the host.
2936
+ // Level-Zero plugin implementation waits for the events to complete
2937
+ // on the host.
2909
2938
ZeEventDesc.signal = ZE_EVENT_SCOPE_FLAG_HOST;
2910
2939
ZeEventDesc.wait = ZE_EVENT_SCOPE_FLAG_HOST;
2911
2940
ZeEventDesc.index = Index;
@@ -3111,7 +3140,11 @@ pi_result piSamplerCreate(pi_context Context,
3111
3140
assert (Context);
3112
3141
assert (RetSampler);
3113
3142
3114
- ze_device_handle_t ZeDevice = Context->Device ->ZeDevice ;
3143
+ // Have the "0" device in context to own the sampler. Rely on Level-Zero
3144
+ // drivers to perform migration as necessary for sharing it across multiple
3145
+ // devices in the context.
3146
+ //
3147
+ pi_device Device = Context->Devices [0 ];
3115
3148
3116
3149
ze_sampler_handle_t ZeSampler;
3117
3150
ze_sampler_desc_t ZeSamplerDesc = {};
@@ -3199,7 +3232,7 @@ pi_result piSamplerCreate(pi_context Context,
3199
3232
}
3200
3233
}
3201
3234
3202
- ZE_CALL (zeSamplerCreate (Context->ZeContext , ZeDevice,
3235
+ ZE_CALL (zeSamplerCreate (Context->ZeContext , Device-> ZeDevice ,
3203
3236
&ZeSamplerDesc, // TODO: translate properties
3204
3237
&ZeSampler));
3205
3238
@@ -4519,14 +4552,16 @@ pi_result piextUSMGetMemAllocInfo(pi_context Context, const void *Ptr,
4519
4552
}
4520
4553
return ReturnValue (MemAllocaType);
4521
4554
}
4522
- case PI_MEM_ALLOC_DEVICE: {
4555
+ case PI_MEM_ALLOC_DEVICE:
4523
4556
if (ZeDeviceHandle) {
4524
- if (Context->Device ->ZeDevice == ZeDeviceHandle) {
4525
- return ReturnValue (Context->Device );
4557
+ auto it = std::find_if (
4558
+ Context->Devices .begin (), Context->Devices .end (),
4559
+ [&](pi_device &D) { return D->ZeDevice == ZeDeviceHandle; });
4560
+ if (it != Context->Devices .end ()) {
4561
+ ReturnValue (*it);
4526
4562
}
4527
4563
}
4528
4564
return PI_INVALID_VALUE;
4529
- }
4530
4565
case PI_MEM_ALLOC_BASE_PTR: {
4531
4566
void *Base;
4532
4567
ZE_CALL (zeMemGetAddressRange (Context->ZeContext , Ptr , &Base, nullptr ));
0 commit comments