diff --git a/unified-runtime/source/adapters/level_zero/common.cpp b/unified-runtime/source/adapters/level_zero/common.cpp index 08bada597..8f5062976 100644 --- a/unified-runtime/source/adapters/level_zero/common.cpp +++ b/unified-runtime/source/adapters/level_zero/common.cpp @@ -273,6 +273,15 @@ template <> ze_structure_type_t getZeStructureType() { return ZE_STRUCTURE_TYPE_DEVICE_MEMORY_EXT_PROPERTIES; } +// BACKPORT(#23028) +#ifdef ZE_DEVICE_USABLEMEM_SIZE_PROPERTIES_EXT_NAME +template <> +ze_structure_type_t +getZeStructureType() { + return ZE_STRUCTURE_TYPE_DEVICE_USABLEMEM_SIZE_EXT_PROPERTIES; +} +#endif +// END_OF_BACKPORT(#23028) template <> ze_structure_type_t getZeStructureType() { return ZE_STRUCTURE_TYPE_DEVICE_IP_VERSION_EXT; diff --git a/unified-runtime/source/adapters/level_zero/device.cpp b/unified-runtime/source/adapters/level_zero/device.cpp index c64c95eb3..43253bd84 100644 --- a/unified-runtime/source/adapters/level_zero/device.cpp +++ b/unified-runtime/source/adapters/level_zero/device.cpp @@ -225,6 +225,48 @@ uint64_t calculateGlobalMemSize(ur_device_handle_t Device) { return Device->ZeGlobalMemSize.get().value; } +// BACKPORT(#23028) +static bool +supportsDeviceUsableMemSizeExtension(ur_platform_handle_t Platform) { +#ifdef ZE_DEVICE_USABLEMEM_SIZE_PROPERTIES_EXT_NAME + constexpr const char *ExtensionName = + ZE_DEVICE_USABLEMEM_SIZE_PROPERTIES_EXT_NAME; + constexpr uint32_t MinVersion = ZE_MAKE_VERSION(1, 0); + + auto Extension = Platform->zeDriverExtensionMap.find(ExtensionName); + return Extension != Platform->zeDriverExtensionMap.end() && + Extension->second >= MinVersion; +#else + std::ignore = Platform; + return false; +#endif +} + +static std::optional +getDeviceUsableMemSizeFromCore(ur_device_handle_t Device) { +#ifdef ZE_DEVICE_USABLEMEM_SIZE_PROPERTIES_EXT_NAME + if (!supportsDeviceUsableMemSizeExtension(Device->Platform)) { + return std::nullopt; + } + + ZeStruct DeviceProperties; + ZeStruct UsableMemProperties; + DeviceProperties.pNext = &UsableMemProperties; + + auto ZeResult = ZE_CALL_NOCHECK(zeDeviceGetProperties, + (Device->ZeDevice, &DeviceProperties)); + if (ZeResult != ZE_RESULT_SUCCESS) { + return std::nullopt; + } + + return UsableMemProperties.currUsableMemSize; +#else + std::ignore = Device; + return std::nullopt; +#endif +} +// END_OF_BACKPORT(#23028) + // Return the Sysman device handle and correpsonding data for the given UR // device. static std::tuple @@ -865,6 +907,32 @@ ur_result_t urDeviceGetInfo( } case UR_DEVICE_INFO_GLOBAL_MEM_FREE: { + // BACKPORT(#23028) + if (!ParamValue && pSize) { + if (supportsDeviceUsableMemSizeExtension(Device->Platform)) { + return ReturnValue(uint64_t{0}); + } + + auto [ZesDevice, ZesDeviceData, Result] = getZesDeviceData(Device); + (void)ZesDeviceData; + if (Result != UR_RESULT_SUCCESS) { + return Result; + } + + // Verify the query actually works so the enumeration isn't falsely + // advertised as supported. + uint32_t MemCount = 0; + if (ZE_CALL_NOCHECK(zesDeviceEnumMemoryModules, + (ZesDevice, &MemCount, nullptr)) != + ZE_RESULT_SUCCESS || + MemCount == 0) { + return UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION; + } + + return ReturnValue(uint64_t{0}); + } + // END_OF_BACKPORT(#23028) + // Calculate the global memory size as the max limit that can be reported as // "free" memory for the user to allocate. uint64_t GlobalMemSize = calculateGlobalMemSize(Device); @@ -873,6 +941,12 @@ ur_result_t urDeviceGetInfo( uint64_t FreeMemory = 0; uint32_t MemCount = 0; + // BACKPORT(#23028) + if (auto CoreUsableMemSize = getDeviceUsableMemSizeFromCore(Device)) { + return ReturnValue(std::min(GlobalMemSize, *CoreUsableMemSize)); + } + // END_OF_BACKPORT(#23028) + auto [ZesDevice, ZesDeviceData, Result] = getZesDeviceData(Device); if (Result != UR_RESULT_SUCCESS) return Result;