Skip to content

Commit bd39fbe

Browse files
authored
Merge pull request #2361 from nrspruit/l0_external_semaphore
[L0] Add Support for External Semaphores
2 parents b23a973 + dc3ca71 commit bd39fbe

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)