From f9da1bdc53031680a5b123b488b781b7ceb53929 Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Fri, 15 Aug 2025 12:34:21 +0100 Subject: [PATCH 1/4] Update urEventSetCallback test to not assume sync. events (#19788) Before this patch, urEventSetCallbackTest assumed that the callback would be executed during and blocking urEventWait or urEventRelease. This change removes that assumptions by having the main thread wait until the callback is complete. --- test/conformance/event/urEventSetCallback.cpp | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/test/conformance/event/urEventSetCallback.cpp b/test/conformance/event/urEventSetCallback.cpp index 7479b50a2a..ac3086a2ec 100644 --- a/test/conformance/event/urEventSetCallback.cpp +++ b/test/conformance/event/urEventSetCallback.cpp @@ -6,9 +6,24 @@ #include "fixtures.h" #include "uur/known_failure.h" +using namespace std::chrono_literals; /* Using urEventReferenceTest to be able to release the event during the test */ -using urEventSetCallbackTest = uur::event::urEventReferenceTest; +struct urEventSetCallbackTest : uur::event::urEventReferenceTest { + std::mutex m; + std::condition_variable cv; + int flag = 0; + + void WaitForFlag(int Target = 1) { + std::unique_lock lk(m); + cv.wait_for(lk, 1000ms, [&] { return flag == Target; }); + } + + void SetFlag() { + flag++; + cv.notify_one(); + } +}; /** * Checks that the callback function is called. @@ -22,19 +37,19 @@ TEST_P(urEventSetCallbackTest, Success) { [[maybe_unused]] ur_execution_info_t execStatus, void *pUserData) { - auto status = reinterpret_cast(pUserData); - *status = true; + auto that = reinterpret_cast(pUserData); + that->SetFlag(); } }; - bool didRun = false; ASSERT_SUCCESS( urEventSetCallback(event, ur_execution_info_t::UR_EXECUTION_INFO_COMPLETE, - Callback::callback, &didRun)); + Callback::callback, this)); ASSERT_SUCCESS(urEventWait(1, &event)); ASSERT_SUCCESS(urEventRelease(event)); - ASSERT_TRUE(didRun); + WaitForFlag(); + ASSERT_EQ(flag, 1); } /** @@ -45,6 +60,7 @@ TEST_P(urEventSetCallbackTest, ValidateParameters) { uur::LevelZeroV2{}, uur::NativeCPU{}); struct CallbackParameters { + urEventSetCallbackTest *test; ur_event_handle_t event; ur_execution_info_t execStatus; }; @@ -56,10 +72,11 @@ TEST_P(urEventSetCallbackTest, ValidateParameters) { auto parameters = reinterpret_cast(pUserData); parameters->event = hEvent; parameters->execStatus = execStatus; + parameters->test->SetFlag(); } }; - CallbackParameters parameters{}; + CallbackParameters parameters{this, nullptr, UR_EXECUTION_INFO_QUEUED}; ASSERT_SUCCESS( urEventSetCallback(event, ur_execution_info_t::UR_EXECUTION_INFO_COMPLETE, @@ -67,6 +84,7 @@ TEST_P(urEventSetCallbackTest, ValidateParameters) { ASSERT_SUCCESS(urEventWait(1, &event)); ASSERT_SUCCESS(urEventRelease(event)); + WaitForFlag(); ASSERT_EQ(event, parameters.event); ASSERT_EQ(ur_execution_info_t::UR_EXECUTION_INFO_COMPLETE, parameters.execStatus); @@ -80,6 +98,7 @@ TEST_P(urEventSetCallbackTest, AllStates) { uur::LevelZeroV2{}, uur::NativeCPU{}); struct CallbackStatus { + urEventSetCallbackTest *test = nullptr; bool submitted = false; bool running = false; bool complete = false; @@ -107,10 +126,12 @@ TEST_P(urEventSetCallbackTest, AllStates) { FAIL() << "Invalid execution info enumeration"; } } + + status->test->SetFlag(); } }; - CallbackStatus status{}; + CallbackStatus status{this}; ASSERT_SUCCESS(urEventSetCallback( event, ur_execution_info_t::UR_EXECUTION_INFO_SUBMITTED, @@ -124,6 +145,7 @@ TEST_P(urEventSetCallbackTest, AllStates) { ASSERT_SUCCESS(urEventWait(1, &event)); ASSERT_SUCCESS(urEventRelease(event)); + WaitForFlag(3); ASSERT_TRUE(status.submitted); ASSERT_TRUE(status.running); @@ -145,19 +167,18 @@ TEST_P(urEventSetCallbackTest, EventAlreadyCompleted) { [[maybe_unused]] ur_execution_info_t execStatus, void *pUserData) { - auto status = reinterpret_cast(pUserData); - *status = true; + auto that = reinterpret_cast(pUserData); + that->SetFlag(); } }; - bool didRun = false; - ASSERT_SUCCESS( urEventSetCallback(event, ur_execution_info_t::UR_EXECUTION_INFO_COMPLETE, - Callback::callback, &didRun)); + Callback::callback, this)); ASSERT_SUCCESS(urEventRelease(event)); - ASSERT_TRUE(didRun); + WaitForFlag(); + ASSERT_EQ(flag, 1); } UUR_INSTANTIATE_DEVICE_TEST_SUITE(urEventSetCallbackTest); From a684cf178b7d19a666e0de8c12244e5bcdf70799 Mon Sep 17 00:00:00 2001 From: Ross Brunton Date: Fri, 15 Aug 2025 12:34:54 +0100 Subject: [PATCH 2/4] Allow `urProgramGetFunctionPointer` to return `UNSUPPORTED` (#19802) This is primarily for liboffload which doesn't support it yet, and probably never will for AMD devices (which don't seem to have this functionality). In theory it will also affect level zero, at least according to a comment, but urProgramGetFunctionPointer seems to be implemented there. --- include/ur_api.h | 2 ++ scripts/core/program.yml | 2 ++ source/adapters/offload/program.cpp | 9 +++++++++ source/adapters/offload/ur_interface_loader.cpp | 2 +- source/loader/ur_libapi.cpp | 2 ++ source/ur_api.cpp | 2 ++ .../program/urProgramGetFunctionPointer.cpp | 16 +++++----------- 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/include/ur_api.h b/include/ur_api.h index 23b33c0f2e..e6f814e178 100644 --- a/include/ur_api.h +++ b/include/ur_api.h @@ -5722,6 +5722,8 @@ UR_APIEXPORT ur_result_t UR_APICALL urProgramRelease( /// - ::UR_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE /// + If `pFunctionName` could be located, but its address couldn't be /// retrieved. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If the backend does not support querying function pointers. UR_APIEXPORT ur_result_t UR_APICALL urProgramGetFunctionPointer( /// [in] handle of the device to retrieve pointer for. ur_device_handle_t hDevice, diff --git a/scripts/core/program.yml b/scripts/core/program.yml index c6c2a9f83d..f2f1259a07 100644 --- a/scripts/core/program.yml +++ b/scripts/core/program.yml @@ -323,6 +323,8 @@ returns: - "If `pFunctionName` couldn't be found in `hProgram`." - $X_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE: - "If `pFunctionName` could be located, but its address couldn't be retrieved." + - $X_RESULT_ERROR_UNSUPPORTED_FEATURE: + - "If the backend does not support querying function pointers." --- #-------------------------------------------------------------------------- type: function desc: "Retrieves a pointer to a device global variable." diff --git a/source/adapters/offload/program.cpp b/source/adapters/offload/program.cpp index b2297b2b4b..ec73469bfb 100644 --- a/source/adapters/offload/program.cpp +++ b/source/adapters/offload/program.cpp @@ -293,3 +293,12 @@ UR_APIEXPORT ur_result_t UR_APICALL urProgramGetGlobalVariablePointer( return UR_RESULT_SUCCESS; } + +UR_APIEXPORT ur_result_t UR_APICALL +urProgramGetFunctionPointer([[maybe_unused]] ur_device_handle_t hDevice, + [[maybe_unused]] ur_program_handle_t hProgram, + [[maybe_unused]] const char *pFunctionName, + [[maybe_unused]] void **ppFunctionPointer) { + // liboffload doesn't support a representation of function pointers (yet) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} diff --git a/source/adapters/offload/ur_interface_loader.cpp b/source/adapters/offload/ur_interface_loader.cpp index 498b09d7da..5b4c8bd13b 100644 --- a/source/adapters/offload/ur_interface_loader.cpp +++ b/source/adapters/offload/ur_interface_loader.cpp @@ -91,7 +91,7 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetProgramProcAddrTable( pDdiTable->pfnCreateWithIL = urProgramCreateWithIL; pDdiTable->pfnCreateWithNativeHandle = urProgramCreateWithNativeHandle; pDdiTable->pfnGetBuildInfo = nullptr; - pDdiTable->pfnGetFunctionPointer = nullptr; + pDdiTable->pfnGetFunctionPointer = urProgramGetFunctionPointer; pDdiTable->pfnGetGlobalVariablePointer = urProgramGetGlobalVariablePointer; pDdiTable->pfnGetInfo = urProgramGetInfo; pDdiTable->pfnGetNativeHandle = urProgramGetNativeHandle; diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp index 286df652fe..a7559029e2 100644 --- a/source/loader/ur_libapi.cpp +++ b/source/loader/ur_libapi.cpp @@ -3438,6 +3438,8 @@ ur_result_t UR_APICALL urProgramRelease( /// - ::UR_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE /// + If `pFunctionName` could be located, but its address couldn't be /// retrieved. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If the backend does not support querying function pointers. ur_result_t UR_APICALL urProgramGetFunctionPointer( /// [in] handle of the device to retrieve pointer for. ur_device_handle_t hDevice, diff --git a/source/ur_api.cpp b/source/ur_api.cpp index be7e5662cd..4709496405 100644 --- a/source/ur_api.cpp +++ b/source/ur_api.cpp @@ -3024,6 +3024,8 @@ ur_result_t UR_APICALL urProgramRelease( /// - ::UR_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE /// + If `pFunctionName` could be located, but its address couldn't be /// retrieved. +/// - ::UR_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + If the backend does not support querying function pointers. ur_result_t UR_APICALL urProgramGetFunctionPointer( /// [in] handle of the device to retrieve pointer for. ur_device_handle_t hDevice, diff --git a/test/conformance/program/urProgramGetFunctionPointer.cpp b/test/conformance/program/urProgramGetFunctionPointer.cpp index 9243701000..83906dc9db 100644 --- a/test/conformance/program/urProgramGetFunctionPointer.cpp +++ b/test/conformance/program/urProgramGetFunctionPointer.cpp @@ -24,7 +24,8 @@ TEST_P(urProgramGetFunctionPointerTest, Success) { void *function_pointer = nullptr; ur_result_t res = urProgramGetFunctionPointer( device, program, function_name.data(), &function_pointer); - if (res == UR_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE) { + if (res == UR_RESULT_ERROR_FUNCTION_ADDRESS_NOT_AVAILABLE || + res == UR_RESULT_ERROR_UNSUPPORTED_FEATURE) { return; } ASSERT_SUCCESS(res); @@ -36,17 +37,10 @@ TEST_P(urProgramGetFunctionPointerTest, InvalidKernelName) { std::string missing_function = "aFakeFunctionName"; auto result = urProgramGetFunctionPointer( device, program, missing_function.data(), &function_pointer); - ur_backend_t backend; - ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND, - sizeof(backend), &backend, nullptr)); - // TODO: level zero backend incorrectly returns - // UR_RESULT_ERROR_UNSUPPORTED_FEATURE - if (backend == UR_BACKEND_LEVEL_ZERO) { - ASSERT_EQ(UR_RESULT_ERROR_UNSUPPORTED_FEATURE, result); - } else { - ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_KERNEL_NAME, result); + if (result == UR_RESULT_ERROR_UNSUPPORTED_FEATURE) { + return; } - + ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_KERNEL_NAME, result); ASSERT_EQ(function_pointer, nullptr); } From bf02ef466d2a2148a0b8634d4b0263ff3ec8e782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Chor=C4=85=C5=BCewicz?= Date: Fri, 15 Aug 2025 07:34:19 -0700 Subject: [PATCH 3/4] Implement missing bindless images functionality (#19808) Implement urBindlessImagesSignalExternalSemaphoreExp and urBindlessImagesWaitExternalSemaphoreExp. The implementation is the same as in the legace adapter, except that we don't to a fallback in case old loader is used (v2 is supposed to be used with a new enough L0 loader version). --- .../level_zero/v2/command_list_manager.cpp | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/source/adapters/level_zero/v2/command_list_manager.cpp b/source/adapters/level_zero/v2/command_list_manager.cpp index 753ad2e0af..9f5fa7e31a 100644 --- a/source/adapters/level_zero/v2/command_list_manager.cpp +++ b/source/adapters/level_zero/v2/command_list_manager.cpp @@ -907,19 +907,66 @@ ur_result_t ur_command_list_manager::bindlessImagesImageCopyExp( } ur_result_t ur_command_list_manager::bindlessImagesWaitExternalSemaphoreExp( - ur_exp_external_semaphore_handle_t /*hSemaphore*/, bool /*hasWaitValue*/, - uint64_t /*waitValue*/, uint32_t /*numEventsInWaitList*/, - const ur_event_handle_t * /*phEventWaitList*/, - ur_event_handle_t /*phEvent*/) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + ur_exp_external_semaphore_handle_t hSemaphore, bool hasWaitValue, + uint64_t waitValue, uint32_t numEventsInWaitList, + const ur_event_handle_t *phEventWaitList, ur_event_handle_t phEvent) { + auto hPlatform = hContext->getPlatform(); + if (!hPlatform->ZeExternalSemaphoreExt.Supported == false || + !hPlatform->ZeExternalSemaphoreExt.LoaderExtension) { + UR_LOG_LEGACY(ERR, + logger::LegacyMessage("[UR][L0] {} function not supported!"), + "{} function not supported!", __FUNCTION__); + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + auto zeSignalEvent = + getSignalEvent(phEvent, UR_COMMAND_EXTERNAL_SEMAPHORE_WAIT_EXP); + auto [pWaitEvents, numWaitEvents] = + getWaitListView(phEventWaitList, numEventsInWaitList); + + ze_external_semaphore_wait_params_ext_t waitParams = { + ZE_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_WAIT_PARAMS_EXT, nullptr, 0}; + waitParams.value = hasWaitValue ? waitValue : 0; + ze_external_semaphore_ext_handle_t hExtSemaphore = + reinterpret_cast(hSemaphore); + ZE2UR_CALL(hPlatform->ZeExternalSemaphoreExt + .zexCommandListAppendWaitExternalSemaphoresExp, + (zeCommandList.get(), 1, &hExtSemaphore, &waitParams, + zeSignalEvent, numWaitEvents, pWaitEvents)); + + return UR_RESULT_SUCCESS; } ur_result_t ur_command_list_manager::bindlessImagesSignalExternalSemaphoreExp( - ur_exp_external_semaphore_handle_t /*hSemaphore*/, bool /*hasSignalValue*/, - uint64_t /*signalValue*/, uint32_t /*numEventsInWaitList*/, - const ur_event_handle_t * /*phEventWaitList*/, - ur_event_handle_t /*phEvent*/) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + ur_exp_external_semaphore_handle_t hSemaphore, bool hasSignalValue, + uint64_t signalValue, uint32_t numEventsInWaitList, + const ur_event_handle_t *phEventWaitList, ur_event_handle_t phEvent) { + auto hPlatform = hContext->getPlatform(); + if (!hPlatform->ZeExternalSemaphoreExt.Supported == false || + !hPlatform->ZeExternalSemaphoreExt.LoaderExtension) { + UR_LOG_LEGACY(ERR, + logger::LegacyMessage("[UR][L0] {} function not supported!"), + "{} function not supported!", __FUNCTION__); + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + auto zeSignalEvent = + getSignalEvent(phEvent, UR_COMMAND_EXTERNAL_SEMAPHORE_SIGNAL_EXP); + auto [pWaitEvents, numWaitEvents] = + getWaitListView(phEventWaitList, numEventsInWaitList); + + ze_external_semaphore_signal_params_ext_t signalParams = { + ZE_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS_EXT, nullptr, 0}; + signalParams.value = hasSignalValue ? signalValue : 0; + ze_external_semaphore_ext_handle_t hExtSemaphore = + reinterpret_cast(hSemaphore); + + ZE2UR_CALL(hPlatform->ZeExternalSemaphoreExt + .zexCommandListAppendSignalExternalSemaphoresExp, + (zeCommandList.get(), 1, &hExtSemaphore, &signalParams, + zeSignalEvent, numWaitEvents, pWaitEvents)); + + return UR_RESULT_SUCCESS; } ur_result_t ur_command_list_manager::appendNativeCommandExp( From e4ae6f9fa50dcdfea9bfc37c8f17f15103116b02 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 16 Aug 2025 00:40:05 +0000 Subject: [PATCH 4/4] Update intel/llvm mirror base commit to cbea6003 --- .github/intel-llvm-mirror-base-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/intel-llvm-mirror-base-commit b/.github/intel-llvm-mirror-base-commit index ccdde2d8ec..6ad41e8832 100644 --- a/.github/intel-llvm-mirror-base-commit +++ b/.github/intel-llvm-mirror-base-commit @@ -1 +1 @@ -84518c193adb9d8b03ae449345d892c6c9984846 +cbea6003f58953ebf25e1ed353d3d7ac37191e8c