diff --git a/include/ur.py b/include/ur.py index 5597773501..e6a54c7153 100644 --- a/include/ur.py +++ b/include/ur.py @@ -196,6 +196,7 @@ class ur_function_v(IntEnum): ADAPTER_RETAIN = 179 ## Enumerator for ::urAdapterRetain ADAPTER_GET_LAST_ERROR = 180 ## Enumerator for ::urAdapterGetLastError ADAPTER_GET_INFO = 181 ## Enumerator for ::urAdapterGetInfo + DEVICE_GET_SELECTED = 182 ## Enumerator for ::urDeviceGetSelected class ur_function_t(c_int): def __str__(self): diff --git a/include/ur_api.h b/include/ur_api.h index 7df48cb743..647c680531 100644 --- a/include/ur_api.h +++ b/include/ur_api.h @@ -205,6 +205,7 @@ typedef enum ur_function_t { UR_FUNCTION_ADAPTER_RETAIN = 179, ///< Enumerator for ::urAdapterRetain UR_FUNCTION_ADAPTER_GET_LAST_ERROR = 180, ///< Enumerator for ::urAdapterGetLastError UR_FUNCTION_ADAPTER_GET_INFO = 181, ///< Enumerator for ::urAdapterGetInfo + UR_FUNCTION_DEVICE_GET_SELECTED = 182, ///< Enumerator for ::urDeviceGetSelected /// @cond UR_FUNCTION_FORCE_UINT32 = 0x7fffffff /// @endcond @@ -1302,6 +1303,46 @@ urDeviceGet( ///< pNumDevices will be updated with the total number of devices available. ); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves devices within a platform selected by ONEAPI_DEVICE_SELECTOR +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The number and order of handles returned from this function will be +/// affected by environment variables that filter or select which devices +/// are exposed through this API. +/// - A reference is taken for each returned device and must be released +/// with a subsequent call to ::urDeviceRelease. +/// - The application may call this function from simultaneous threads, the +/// implementation must be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_DEVICE_TYPE_VPU < DeviceType` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +UR_APIEXPORT ur_result_t UR_APICALL +urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t *phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. +); + /////////////////////////////////////////////////////////////////////////////// /// @brief Supported device info typedef enum ur_device_info_t { @@ -10179,6 +10220,18 @@ typedef struct ur_device_get_params_t { uint32_t **ppNumDevices; } ur_device_get_params_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urDeviceGetSelected +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_device_get_selected_params_t { + ur_platform_handle_t *phPlatform; + ur_device_type_t *pDeviceType; + uint32_t *pNumEntries; + ur_device_handle_t **pphDevices; + uint32_t **ppNumDevices; +} ur_device_get_selected_params_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Function parameters for urDeviceGetInfo /// @details Each entry is a pointer to the parameter passed to the function; diff --git a/scripts/core/device.yml b/scripts/core/device.yml index 4fd4b09d93..8ca2895596 100644 --- a/scripts/core/device.yml +++ b/scripts/core/device.yml @@ -141,6 +141,45 @@ params: returns: - $X_RESULT_ERROR_INVALID_VALUE --- #-------------------------------------------------------------------------- +type: function +desc: "Retrieves devices within a platform selected by ONEAPI_DEVICE_SELECTOR" +class: $xDevice +loader_only: True +name: GetSelected +decl: static +ordinal: "0" +details: + - "Multiple calls to this function will return identical device handles, in the same order." + - "The number and order of handles returned from this function will be affected by environment variables that filter or select which devices are exposed through this API." + - "A reference is taken for each returned device and must be released with a subsequent call to $xDeviceRelease." + - "The application may call this function from simultaneous threads, the implementation must be thread-safe." +params: + - type: $x_platform_handle_t + name: hPlatform + desc: "[in] handle of the platform instance" + - type: "$x_device_type_t" + name: DeviceType + desc: | + [in] the type of the devices. + - type: "uint32_t" + name: NumEntries + desc: | + [in] the number of devices to be added to phDevices. + If phDevices in not NULL then NumEntries should be greater than zero, otherwise $X_RESULT_ERROR_INVALID_VALUE, + will be returned. + - type: "$x_device_handle_t*" + name: phDevices + desc: | + [out][optional][range(0, NumEntries)] array of handle of devices. + If NumEntries is less than the number of devices available, then only that number of devices will be retrieved. + - type: "uint32_t*" + name: pNumDevices + desc: | + [out][optional] pointer to the number of devices. + pNumDevices will be updated with the total number of selected devices available for the given platform. +returns: + - $X_RESULT_ERROR_INVALID_VALUE +--- #-------------------------------------------------------------------------- type: enum desc: "Supported device info" class: $xDevice diff --git a/scripts/core/registry.yml b/scripts/core/registry.yml index 30596ec14e..95cdbfdc0e 100644 --- a/scripts/core/registry.yml +++ b/scripts/core/registry.yml @@ -529,6 +529,9 @@ etors: - name: ADAPTER_GET_INFO desc: Enumerator for $xAdapterGetInfo value: '181' +- name: DEVICE_GET_SELECTED + desc: Enumerator for $xDeviceGetSelected + value: '182' --- type: enum desc: Defines structure types diff --git a/source/adapters/null/ur_nullddi.cpp b/source/adapters/null/ur_nullddi.cpp index f9b8fb4d11..1d33f91341 100644 --- a/source/adapters/null/ur_nullddi.cpp +++ b/source/adapters/null/ur_nullddi.cpp @@ -393,6 +393,44 @@ __urdlllocal ur_result_t UR_APICALL urDeviceGet( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urDeviceGetSelected +__urdlllocal ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. + ) try { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnGetSelected = d_context.urDdiTable.Device.pfnGetSelected; + if (nullptr != pfnGetSelected) { + result = pfnGetSelected(hPlatform, DeviceType, NumEntries, phDevices, + pNumDevices); + } else { + // generic implementation + for (size_t i = 0; (nullptr != phDevices) && (i < NumEntries); ++i) { + phDevices[i] = + reinterpret_cast(d_context.get()); + } + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urDeviceGetInfo __urdlllocal ur_result_t UR_APICALL urDeviceGetInfo( diff --git a/source/common/ur_params.hpp b/source/common/ur_params.hpp index 2f9789506e..96043141f3 100644 --- a/source/common/ur_params.hpp +++ b/source/common/ur_params.hpp @@ -1112,6 +1112,10 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_function_t value) { case UR_FUNCTION_ADAPTER_GET_INFO: os << "UR_FUNCTION_ADAPTER_GET_INFO"; break; + + case UR_FUNCTION_DEVICE_GET_SELECTED: + os << "UR_FUNCTION_DEVICE_GET_SELECTED"; + break; default: os << "unknown enumerator"; break; @@ -14951,6 +14955,44 @@ inline std::ostream &operator<<(std::ostream &os, return os; } +inline std::ostream & +operator<<(std::ostream &os, + const struct ur_device_get_selected_params_t *params) { + + os << ".hPlatform = "; + + ur_params::serializePtr(os, *(params->phPlatform)); + + os << ", "; + os << ".DeviceType = "; + + os << *(params->pDeviceType); + + os << ", "; + os << ".NumEntries = "; + + os << *(params->pNumEntries); + + os << ", "; + os << ".phDevices = {"; + for (size_t i = 0; + *(params->pphDevices) != NULL && i < *params->pNumEntries; ++i) { + if (i != 0) { + os << ", "; + } + + ur_params::serializePtr(os, (*(params->pphDevices))[i]); + } + os << "}"; + + os << ", "; + os << ".pNumDevices = "; + + ur_params::serializePtr(os, *(params->ppNumDevices)); + + return os; +} + inline std::ostream & operator<<(std::ostream &os, const struct ur_device_get_info_params_t *params) { @@ -15688,6 +15730,9 @@ inline int serializeFunctionParams(std::ostream &os, uint32_t function, case UR_FUNCTION_DEVICE_GET: { os << (const struct ur_device_get_params_t *)params; } break; + case UR_FUNCTION_DEVICE_GET_SELECTED: { + os << (const struct ur_device_get_selected_params_t *)params; + } break; case UR_FUNCTION_DEVICE_GET_INFO: { os << (const struct ur_device_get_info_params_t *)params; } break; diff --git a/source/loader/layers/tracing/ur_trcddi.cpp b/source/loader/layers/tracing/ur_trcddi.cpp index f30fac3807..9d01fb903e 100644 --- a/source/loader/layers/tracing/ur_trcddi.cpp +++ b/source/loader/layers/tracing/ur_trcddi.cpp @@ -435,6 +435,44 @@ __urdlllocal ur_result_t UR_APICALL urDeviceGet( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urDeviceGetSelected +__urdlllocal ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. +) { + auto pfnGetSelected = context.urDdiTable.Device.pfnGetSelected; + + if (nullptr == pfnGetSelected) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + ur_device_get_selected_params_t params = { + &hPlatform, &DeviceType, &NumEntries, &phDevices, &pNumDevices}; + uint64_t instance = context.notify_begin(UR_FUNCTION_DEVICE_GET_SELECTED, + "urDeviceGetSelected", ¶ms); + + ur_result_t result = pfnGetSelected(hPlatform, DeviceType, NumEntries, + phDevices, pNumDevices); + + context.notify_end(UR_FUNCTION_DEVICE_GET_SELECTED, "urDeviceGetSelected", + ¶ms, &result, instance); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urDeviceGetInfo __urdlllocal ur_result_t UR_APICALL urDeviceGetInfo( diff --git a/source/loader/layers/validation/ur_valddi.cpp b/source/loader/layers/validation/ur_valddi.cpp index 46b0eef491..11f0a98a72 100644 --- a/source/loader/layers/validation/ur_valddi.cpp +++ b/source/loader/layers/validation/ur_valddi.cpp @@ -477,6 +477,46 @@ __urdlllocal ur_result_t UR_APICALL urDeviceGet( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urDeviceGetSelected +__urdlllocal ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. +) { + auto pfnGetSelected = context.urDdiTable.Device.pfnGetSelected; + + if (nullptr == pfnGetSelected) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (context.enableParameterValidation) { + if (NULL == hPlatform) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (UR_DEVICE_TYPE_VPU < DeviceType) { + return UR_RESULT_ERROR_INVALID_ENUMERATION; + } + } + + ur_result_t result = pfnGetSelected(hPlatform, DeviceType, NumEntries, + phDevices, pNumDevices); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urDeviceGetInfo __urdlllocal ur_result_t UR_APICALL urDeviceGetInfo( diff --git a/source/loader/ur_ldrddi.cpp b/source/loader/ur_ldrddi.cpp index e192088bbc..31c9e6dff6 100644 --- a/source/loader/ur_ldrddi.cpp +++ b/source/loader/ur_ldrddi.cpp @@ -518,6 +518,58 @@ __urdlllocal ur_result_t UR_APICALL urDeviceGet( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urDeviceGetSelected +__urdlllocal ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. +) { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = + reinterpret_cast(hPlatform)->dditable; + auto pfnGetSelected = dditable->ur.Device.pfnGetSelected; + if (nullptr == pfnGetSelected) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + // convert loader handle to platform handle + hPlatform = reinterpret_cast(hPlatform)->handle; + + // forward to device-platform + result = pfnGetSelected(hPlatform, DeviceType, NumEntries, phDevices, + pNumDevices); + + if (UR_RESULT_SUCCESS != result) { + return result; + } + + try { + // convert platform handles to loader handles + for (size_t i = 0; (nullptr != phDevices) && (i < NumEntries); ++i) { + phDevices[i] = reinterpret_cast( + ur_device_factory.getInstance(phDevices[i], dditable)); + } + } catch (std::bad_alloc &) { + result = UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urDeviceGetInfo __urdlllocal ur_result_t UR_APICALL urDeviceGetInfo( diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp index 9c7060fdbe..007394eb64 100644 --- a/source/loader/ur_libapi.cpp +++ b/source/loader/ur_libapi.cpp @@ -749,6 +749,52 @@ ur_result_t UR_APICALL urDeviceGet( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves devices within a platform selected by ONEAPI_DEVICE_SELECTOR +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The number and order of handles returned from this function will be +/// affected by environment variables that filter or select which devices +/// are exposed through this API. +/// - A reference is taken for each returned device and must be released +/// with a subsequent call to ::urDeviceRelease. +/// - The application may call this function from simultaneous threads, the +/// implementation must be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_DEVICE_TYPE_VPU < DeviceType` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. + ) try { + return ur_lib::urDeviceGetSelected(hPlatform, DeviceType, NumEntries, + phDevices, pNumDevices); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Retrieves various information about device /// diff --git a/source/ur_api.cpp b/source/ur_api.cpp index 424290d88f..413c24ba29 100644 --- a/source/ur_api.cpp +++ b/source/ur_api.cpp @@ -638,6 +638,50 @@ ur_result_t UR_APICALL urDeviceGet( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retrieves devices within a platform selected by ONEAPI_DEVICE_SELECTOR +/// +/// @details +/// - Multiple calls to this function will return identical device handles, +/// in the same order. +/// - The number and order of handles returned from this function will be +/// affected by environment variables that filter or select which devices +/// are exposed through this API. +/// - A reference is taken for each returned device and must be released +/// with a subsequent call to ::urDeviceRelease. +/// - The application may call this function from simultaneous threads, the +/// implementation must be thread-safe. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hPlatform` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_DEVICE_TYPE_VPU < DeviceType` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +ur_result_t UR_APICALL urDeviceGetSelected( + ur_platform_handle_t hPlatform, ///< [in] handle of the platform instance + ur_device_type_t DeviceType, ///< [in] the type of the devices. + uint32_t + NumEntries, ///< [in] the number of devices to be added to phDevices. + ///< If phDevices in not NULL then NumEntries should be greater than zero, + ///< otherwise ::UR_RESULT_ERROR_INVALID_VALUE, + ///< will be returned. + ur_device_handle_t * + phDevices, ///< [out][optional][range(0, NumEntries)] array of handle of devices. + ///< If NumEntries is less than the number of devices available, then only + ///< that number of devices will be retrieved. + uint32_t *pNumDevices ///< [out][optional] pointer to the number of devices. + ///< pNumDevices will be updated with the total number of selected devices + ///< available for the given platform. +) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Retrieves various information about device ///