Skip to content

Commit dc3ca71

Browse files
committed
[L0] Add Support for External Semaphores
- Added support for using the Intel L0 driver experimental extension for external sempahores. - This implementation enables support for external semaphores that will exist in a future L0 Intel GPU Driver implementation. - The functionality outlined in this commit mirrors the planned functionality that will be published in the next offical L0 spec release 1.12. Once the L0 1.12 spec is released, then the usage of the header definitions of this functionality will be updated to match the official spec while supporting the previous driver implementation. Signed-off-by: Neil R. Spruit <[email protected]>
1 parent 2bea25d commit dc3ca71

File tree

4 files changed

+296
-27
lines changed

4 files changed

+296
-27
lines changed

source/adapters/level_zero/common.hpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,3 +531,76 @@ extern thread_local int32_t ErrorAdapterNativeCode;
531531
int32_t AdapterErrorCode);
532532

533533
#define L0_DRIVER_INORDER_MIN_VERSION 29534
534+
535+
// Definitions for the External Semaphore Extension
536+
537+
#ifndef ZE_INTEL_EXTERNAL_SEMAPHORE_EXP_NAME
538+
/// @brief Event sync mode extension name
539+
#define ZE_INTEL_EXTERNAL_SEMAPHORE_EXP_NAME \
540+
"ZE_intel_experimental_external_semaphore"
541+
#endif // ZE_INTEL_EXTERNAL_SEMAPHORE_EXP_NAME
542+
543+
typedef enum _ze_intel_external_semaphore_exp_version_t {
544+
ZE_EXTERNAL_SEMAPHORE_EXP_VERSION_1_0 =
545+
ZE_MAKE_VERSION(1, 0), ///< version 1.0
546+
ZE_EXTERNAL_SEMAPHORE_EXP_VERSION_CURRENT =
547+
ZE_MAKE_VERSION(1, 0), ///< latest known version
548+
ZE_EXTERNAL_SEMAPHORE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
549+
} ze_intel_external_semaphore_exp_version_t;
550+
typedef enum _ze_intel_external_semaphore_exp_flags_t {
551+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_FD,
552+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_WIN32,
553+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_WIN32_KMT,
554+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_D3D12_FENCE,
555+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_D3D11_FENCE,
556+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_KEYED_MUTEX,
557+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_KEYED_MUTEX_KMT,
558+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_TIMELINE_SEMAPHORE_FD,
559+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_TIMELINE_SEMAPHORE_WIN32
560+
} ze_intel_external_semaphore_exp_flags_t;
561+
562+
typedef struct _ze_intel_external_semaphore_exp_desc_t {
563+
ze_structure_type_t stype;
564+
const void *pNext;
565+
ze_intel_external_semaphore_exp_flags_t flags;
566+
} ze_intel_external_semaphore_exp_desc_t;
567+
568+
typedef struct _ze_intel_external_semaphore_win32_exp_desc_t {
569+
ze_structure_type_t stype;
570+
const void *pNext;
571+
void *handle;
572+
const char *name;
573+
} ze_intel_external_semaphore_win32_exp_desc_t;
574+
575+
typedef struct _ze_intel_external_semaphore_fd_exp_desc_t {
576+
ze_structure_type_t stype;
577+
const void *pNext;
578+
int fd;
579+
} ze_intel_external_semaphore_desc_fd_exp_desc_t;
580+
581+
typedef struct _ze_intel_external_semaphore_signal_exp_params_t {
582+
ze_structure_type_t stype;
583+
const void *pNext;
584+
uint64_t value;
585+
} ze_intel_external_semaphore_signal_exp_params_t;
586+
587+
typedef struct _ze_intel_external_semaphore_wait_exp_params_t {
588+
ze_structure_type_t stype;
589+
const void *pNext;
590+
591+
uint64_t value;
592+
} ze_intel_external_semaphore_wait_exp_params_t;
593+
594+
typedef struct _ze_intel_external_semaphore_exp_handle_t
595+
*ze_intel_external_semaphore_exp_handle_t;
596+
597+
#define ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_EXP_DESC \
598+
(ze_structure_type_t)0x0003001E
599+
#define ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_WIN32_EXP_DESC \
600+
(ze_structure_type_t)0x0003001F
601+
#define ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_FD_EXP_DESC \
602+
(ze_structure_type_t)0x00030023
603+
#define ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS_EXP \
604+
(ze_structure_type_t)0x00030024
605+
#define ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_WAIT_PARAMS_EXP \
606+
(ze_structure_type_t)0x00030025

source/adapters/level_zero/image.cpp

Lines changed: 162 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,41 +1190,130 @@ ur_result_t urBindlessImagesImportExternalSemaphoreExp(
11901190
ur_exp_external_semaphore_type_t semHandleType,
11911191
ur_exp_external_semaphore_desc_t *pExternalSemaphoreDesc,
11921192
ur_exp_external_semaphore_handle_t *phExternalSemaphoreHandle) {
1193-
std::ignore = hContext;
1194-
std::ignore = hDevice;
1195-
std::ignore = semHandleType;
1196-
std::ignore = pExternalSemaphoreDesc;
1197-
std::ignore = phExternalSemaphoreHandle;
1198-
logger::error(logger::LegacyMessage("[UR][L0] {} function not implemented!"),
1199-
"{} function not implemented!", __FUNCTION__);
1200-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1193+
1194+
auto UrPlatform = hContext->getPlatform();
1195+
if (UrPlatform->ZeExternalSemaphoreExt.Supported == false) {
1196+
logger::error(logger::LegacyMessage("[UR][L0] "),
1197+
" {} function not supported!", __FUNCTION__);
1198+
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1199+
}
1200+
ze_intel_external_semaphore_exp_desc_t SemDesc = {
1201+
ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_EXP_DESC, nullptr,
1202+
ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_FD};
1203+
ze_intel_external_semaphore_exp_handle_t ExtSemaphoreHandle;
1204+
ze_intel_external_semaphore_desc_fd_exp_desc_t FDExpDesc = {
1205+
ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_FD_EXP_DESC, nullptr, 0};
1206+
_ze_intel_external_semaphore_win32_exp_desc_t Win32ExpDesc = {
1207+
ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_WIN32_EXP_DESC, nullptr,
1208+
nullptr, nullptr};
1209+
void *pNext = const_cast<void *>(pExternalSemaphoreDesc->pNext);
1210+
while (pNext != nullptr) {
1211+
const ur_base_desc_t *BaseDesc = static_cast<const ur_base_desc_t *>(pNext);
1212+
if (BaseDesc->stype == UR_STRUCTURE_TYPE_EXP_FILE_DESCRIPTOR) {
1213+
auto FileDescriptor =
1214+
static_cast<const ur_exp_file_descriptor_t *>(pNext);
1215+
FDExpDesc.fd = FileDescriptor->fd;
1216+
SemDesc.pNext = &FDExpDesc;
1217+
SemDesc.flags = ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_FD;
1218+
} else if (BaseDesc->stype == UR_STRUCTURE_TYPE_EXP_WIN32_HANDLE) {
1219+
SemDesc.pNext = &Win32ExpDesc;
1220+
auto Win32Handle = static_cast<const ur_exp_win32_handle_t *>(pNext);
1221+
switch (semHandleType) {
1222+
case UR_EXP_EXTERNAL_SEMAPHORE_TYPE_WIN32_NT:
1223+
SemDesc.flags = ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_WIN32;
1224+
break;
1225+
case UR_EXP_EXTERNAL_SEMAPHORE_TYPE_WIN32_NT_DX12_FENCE:
1226+
SemDesc.flags = ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_D3D12_FENCE;
1227+
break;
1228+
case UR_EXP_EXTERNAL_SEMAPHORE_TYPE_OPAQUE_FD:
1229+
SemDesc.flags = ZE_EXTERNAL_SEMAPHORE_EXP_FLAGS_OPAQUE_FD;
1230+
break;
1231+
default:
1232+
return UR_RESULT_ERROR_INVALID_VALUE;
1233+
}
1234+
Win32ExpDesc.handle = Win32Handle->handle;
1235+
}
1236+
pNext = const_cast<void *>(BaseDesc->pNext);
1237+
}
1238+
1239+
ZE2UR_CALL(UrPlatform->ZeExternalSemaphoreExt.zexImportExternalSemaphoreExp,
1240+
(hDevice->ZeDevice, &ExtSemaphoreHandle, &SemDesc));
1241+
*phExternalSemaphoreHandle =
1242+
(ur_exp_external_semaphore_handle_t)ExtSemaphoreHandle;
1243+
1244+
return UR_RESULT_SUCCESS;
12011245
}
12021246

12031247
ur_result_t urBindlessImagesReleaseExternalSemaphoreExp(
12041248
ur_context_handle_t hContext, ur_device_handle_t hDevice,
12051249
ur_exp_external_semaphore_handle_t hExternalSemaphore) {
1206-
std::ignore = hContext;
12071250
std::ignore = hDevice;
1208-
std::ignore = hExternalSemaphore;
1209-
logger::error(logger::LegacyMessage("[UR][L0] {} function not implemented!"),
1210-
"{} function not implemented!", __FUNCTION__);
1211-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1251+
auto UrPlatform = hContext->getPlatform();
1252+
if (UrPlatform->ZeExternalSemaphoreExt.Supported == false) {
1253+
logger::error(logger::LegacyMessage("[UR][L0] "),
1254+
" {} function not supported!", __FUNCTION__);
1255+
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1256+
}
1257+
ZE2UR_CALL(
1258+
UrPlatform->ZeExternalSemaphoreExt.zexDeviceReleaseExternalSemaphoreExp,
1259+
((ze_intel_external_semaphore_exp_handle_t)hExternalSemaphore));
1260+
1261+
return UR_RESULT_SUCCESS;
12121262
}
12131263

12141264
ur_result_t urBindlessImagesWaitExternalSemaphoreExp(
12151265
ur_queue_handle_t hQueue, ur_exp_external_semaphore_handle_t hSemaphore,
12161266
bool hasValue, uint64_t waitValue, uint32_t numEventsInWaitList,
12171267
const ur_event_handle_t *phEventWaitList, ur_event_handle_t *phEvent) {
1218-
std::ignore = hQueue;
1219-
std::ignore = hSemaphore;
1220-
std::ignore = hasValue;
1221-
std::ignore = waitValue;
1222-
std::ignore = numEventsInWaitList;
1223-
std::ignore = phEventWaitList;
1224-
std::ignore = phEvent;
1225-
logger::error(logger::LegacyMessage("[UR][L0] "),
1226-
" {} function not implemented!", __FUNCTION__);
1227-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1268+
auto UrPlatform = hQueue->Context->getPlatform();
1269+
if (UrPlatform->ZeExternalSemaphoreExt.Supported == false) {
1270+
logger::error(logger::LegacyMessage("[UR][L0] "),
1271+
" {} function not supported!", __FUNCTION__);
1272+
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1273+
}
1274+
1275+
bool UseCopyEngine = false;
1276+
1277+
// We want to batch these commands to avoid extra submissions (costly)
1278+
bool OkToBatch = true;
1279+
1280+
_ur_ze_event_list_t TmpWaitList;
1281+
UR_CALL(TmpWaitList.createAndRetainUrZeEventList(
1282+
numEventsInWaitList, phEventWaitList, hQueue, UseCopyEngine));
1283+
1284+
// Get a new command list to be used on this call
1285+
ur_command_list_ptr_t CommandList{};
1286+
UR_CALL(hQueue->Context->getAvailableCommandList(
1287+
hQueue, CommandList, UseCopyEngine, numEventsInWaitList, phEventWaitList,
1288+
OkToBatch, nullptr /*ForcedCmdQueue*/));
1289+
1290+
ze_event_handle_t ZeEvent = nullptr;
1291+
ur_event_handle_t InternalEvent;
1292+
bool IsInternal = phEvent == nullptr;
1293+
ur_event_handle_t *Event = phEvent ? phEvent : &InternalEvent;
1294+
UR_CALL(createEventAndAssociateQueue(hQueue, Event,
1295+
UR_COMMAND_EXTERNAL_SEMAPHORE_WAIT_EXP,
1296+
CommandList, IsInternal,
1297+
/*IsMultiDevice*/ false));
1298+
UR_CALL(setSignalEvent(hQueue, UseCopyEngine, &ZeEvent, Event,
1299+
numEventsInWaitList, phEventWaitList,
1300+
CommandList->second.ZeQueue));
1301+
(*Event)->WaitList = TmpWaitList;
1302+
1303+
const auto &ZeCommandList = CommandList->first;
1304+
const auto &WaitList = (*Event)->WaitList;
1305+
1306+
ze_intel_external_semaphore_wait_exp_params_t WaitParams = {
1307+
ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_WAIT_PARAMS_EXP, nullptr, 0};
1308+
WaitParams.value = hasValue ? waitValue : 0;
1309+
const ze_intel_external_semaphore_exp_handle_t hExtSemaphore =
1310+
reinterpret_cast<ze_intel_external_semaphore_exp_handle_t>(hSemaphore);
1311+
ZE2UR_CALL(UrPlatform->ZeExternalSemaphoreExt
1312+
.zexCommandListAppendWaitExternalSemaphoresExp,
1313+
(ZeCommandList, &hExtSemaphore, &WaitParams, 1, ZeEvent,
1314+
WaitList.Length, WaitList.ZeEventList));
1315+
1316+
return UR_RESULT_SUCCESS;
12281317
}
12291318

12301319
ur_result_t urBindlessImagesSignalExternalSemaphoreExp(
@@ -1238,9 +1327,56 @@ ur_result_t urBindlessImagesSignalExternalSemaphoreExp(
12381327
std::ignore = numEventsInWaitList;
12391328
std::ignore = phEventWaitList;
12401329
std::ignore = phEvent;
1241-
logger::error(logger::LegacyMessage("[UR][L0] {} function not implemented!"),
1242-
"{} function not implemented!", __FUNCTION__);
1243-
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1330+
auto UrPlatform = hQueue->Context->getPlatform();
1331+
if (UrPlatform->ZeExternalSemaphoreExt.Supported == false) {
1332+
logger::error(logger::LegacyMessage("[UR][L0] "),
1333+
" {} function not supported!", __FUNCTION__);
1334+
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
1335+
}
1336+
1337+
bool UseCopyEngine = false;
1338+
1339+
// We want to batch these commands to avoid extra submissions (costly)
1340+
bool OkToBatch = true;
1341+
1342+
_ur_ze_event_list_t TmpWaitList;
1343+
UR_CALL(TmpWaitList.createAndRetainUrZeEventList(
1344+
numEventsInWaitList, phEventWaitList, hQueue, UseCopyEngine));
1345+
1346+
// Get a new command list to be used on this call
1347+
ur_command_list_ptr_t CommandList{};
1348+
UR_CALL(hQueue->Context->getAvailableCommandList(
1349+
hQueue, CommandList, UseCopyEngine, numEventsInWaitList, phEventWaitList,
1350+
OkToBatch, nullptr /*ForcedCmdQueue*/));
1351+
1352+
ze_event_handle_t ZeEvent = nullptr;
1353+
ur_event_handle_t InternalEvent;
1354+
bool IsInternal = phEvent == nullptr;
1355+
ur_event_handle_t *Event = phEvent ? phEvent : &InternalEvent;
1356+
UR_CALL(createEventAndAssociateQueue(hQueue, Event,
1357+
UR_COMMAND_EXTERNAL_SEMAPHORE_SIGNAL_EXP,
1358+
CommandList, IsInternal,
1359+
/*IsMultiDevice*/ false));
1360+
UR_CALL(setSignalEvent(hQueue, UseCopyEngine, &ZeEvent, Event,
1361+
numEventsInWaitList, phEventWaitList,
1362+
CommandList->second.ZeQueue));
1363+
(*Event)->WaitList = TmpWaitList;
1364+
1365+
const auto &ZeCommandList = CommandList->first;
1366+
const auto &WaitList = (*Event)->WaitList;
1367+
1368+
ze_intel_external_semaphore_signal_exp_params_t SignalParams = {
1369+
ZE_INTEL_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS_EXP, nullptr, 0};
1370+
SignalParams.value = hasValue ? signalValue : 0;
1371+
const ze_intel_external_semaphore_exp_handle_t hExtSemaphore =
1372+
reinterpret_cast<ze_intel_external_semaphore_exp_handle_t>(hSemaphore);
1373+
1374+
ZE2UR_CALL(UrPlatform->ZeExternalSemaphoreExt
1375+
.zexCommandListAppendSignalExternalSemaphoresExp,
1376+
(ZeCommandList, &hExtSemaphore, &SignalParams, 1, ZeEvent,
1377+
WaitList.Length, WaitList.ZeEventList));
1378+
1379+
return UR_RESULT_SUCCESS;
12441380
}
12451381

12461382
} // namespace ur::level_zero

source/adapters/level_zero/platform.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ ur_result_t ur_platform_handle_t_::initialize() {
221221
(ZeDriver, &Count, ZeExtensions.data()));
222222

223223
bool MutableCommandListSpecExtensionSupported = false;
224+
bool ZeIntelExternalSemaphoreExtensionSupported = false;
224225
for (auto &extension : ZeExtensions) {
225226
// Check if global offset extension is available
226227
if (strncmp(extension.name, ZE_GLOBAL_OFFSET_EXP_NAME,
@@ -252,6 +253,13 @@ ur_result_t ur_platform_handle_t_::initialize() {
252253
MutableCommandListSpecExtensionSupported = true;
253254
}
254255
}
256+
// Check if extension is available for External Sempahores
257+
if (strncmp(extension.name, ZE_INTEL_EXTERNAL_SEMAPHORE_EXP_NAME,
258+
strlen(ZE_INTEL_EXTERNAL_SEMAPHORE_EXP_NAME) + 1) == 0) {
259+
if (extension.version == ZE_EXTERNAL_SEMAPHORE_EXP_VERSION_1_0) {
260+
ZeIntelExternalSemaphoreExtensionSupported = true;
261+
}
262+
}
255263
zeDriverExtensionMap[extension.name] = extension.version;
256264
}
257265

@@ -286,6 +294,38 @@ ur_result_t ur_platform_handle_t_::initialize() {
286294
// If yes, then set up L0 API pointers if the platform supports it.
287295
ZeUSMImport.setZeUSMImport(this);
288296

297+
if (ZeIntelExternalSemaphoreExtensionSupported) {
298+
ZeExternalSemaphoreExt.Supported |=
299+
(ZE_CALL_NOCHECK(
300+
zeDriverGetExtensionFunctionAddress,
301+
(ZeDriver, "zeIntelDeviceImportExternalSemaphoreExp",
302+
reinterpret_cast<void **>(
303+
&ZeExternalSemaphoreExt.zexImportExternalSemaphoreExp))) ==
304+
0);
305+
ZeExternalSemaphoreExt.Supported |=
306+
(ZE_CALL_NOCHECK(
307+
zeDriverGetExtensionFunctionAddress,
308+
(ZeDriver, "zeIntelCommandListAppendWaitExternalSemaphoresExp",
309+
reinterpret_cast<void **>(
310+
&ZeExternalSemaphoreExt
311+
.zexCommandListAppendWaitExternalSemaphoresExp))) == 0);
312+
ZeExternalSemaphoreExt.Supported |=
313+
(ZE_CALL_NOCHECK(
314+
zeDriverGetExtensionFunctionAddress,
315+
(ZeDriver, "zeIntelCommandListAppendSignalExternalSemaphoresExp",
316+
reinterpret_cast<void **>(
317+
&ZeExternalSemaphoreExt
318+
.zexCommandListAppendSignalExternalSemaphoresExp))) ==
319+
0);
320+
ZeExternalSemaphoreExt.Supported |=
321+
(ZE_CALL_NOCHECK(zeDriverGetExtensionFunctionAddress,
322+
(ZeDriver, "zeIntelDeviceReleaseExternalSemaphoreExp",
323+
reinterpret_cast<void **>(
324+
&ZeExternalSemaphoreExt
325+
.zexDeviceReleaseExternalSemaphoreExp))) ==
326+
0);
327+
}
328+
289329
// Check if mutable command list extension is supported and initialize
290330
// function pointers.
291331
if (MutableCommandListSpecExtensionSupported) {

source/adapters/level_zero/platform.hpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,24 @@ struct ur_platform_handle_t_ : public _ur_platform {
114114
ze_command_list_handle_t, const ze_mutable_command_id_exp_desc_t *,
115115
uint32_t, ze_kernel_handle_t *, uint64_t *) = nullptr;
116116
} ZeMutableCmdListExt;
117-
};
117+
118+
// Structure with function pointers for External Semaphore Extension.
119+
struct ZeExternalSemaphoreExtension {
120+
bool Supported = false;
121+
ze_result_t (*zexImportExternalSemaphoreExp)(
122+
ze_device_handle_t, ze_intel_external_semaphore_exp_handle_t *,
123+
const ze_intel_external_semaphore_exp_desc_t *);
124+
ze_result_t (*zexCommandListAppendWaitExternalSemaphoresExp)(
125+
ze_command_list_handle_t,
126+
const ze_intel_external_semaphore_exp_handle_t *,
127+
const ze_intel_external_semaphore_wait_exp_params_t *, unsigned int,
128+
ze_event_handle_t, uint32_t, ze_event_handle_t *);
129+
ze_result_t (*zexCommandListAppendSignalExternalSemaphoresExp)(
130+
ze_command_list_handle_t,
131+
const ze_intel_external_semaphore_exp_handle_t *,
132+
const ze_intel_external_semaphore_signal_exp_params_t *, size_t,
133+
ze_event_handle_t, uint32_t, ze_event_handle_t *);
134+
ze_result_t (*zexDeviceReleaseExternalSemaphoreExp)(
135+
ze_intel_external_semaphore_exp_handle_t);
136+
} ZeExternalSemaphoreExt;
137+
};

0 commit comments

Comments
 (0)