[llvm] [offload][l0] Implement context groups and add actual L0 driver version to info (PR #217562)

Jan Trusiłło via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 24 03:53:31 PDT 2026


https://github.com/311Volt updated https://github.com/llvm/llvm-project/pull/217562

>From e13332099d0f4441afaeaee4da89eb939de14bed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Wed, 19 Aug 2026 15:17:21 +0000
Subject: [PATCH 1/7] implement context groups and add actual l0 driver ver to
 info

---
 libsycl/src/detail/device_impl.hpp            | 13 ++++++-
 libsycl/src/detail/platform_impl.cpp          | 30 +++++++++++-----
 libsycl/src/detail/platform_impl.hpp          | 13 +++----
 libsycl/src/detail/queue_impl.cpp             |  2 +-
 .../device_selector/get_device_preference.cpp | 10 ++++++
 libsycl/unittests/mock/helpers.cpp            |  9 +++++
 offload/liboffload/API/Context.td             |  5 +--
 offload/liboffload/API/Device.td              |  3 ++
 offload/liboffload/src/OffloadImpl.cpp        | 20 +++++++++++
 .../common/include/PluginInterface.h          |  6 ++++
 .../level_zero/dynamic_l0/L0DynWrapper.cpp    |  1 +
 .../level_zero/dynamic_l0/level_zero/ze_api.h | 17 ++++++++-
 .../level_zero/include/L0Context.h            |  5 +++
 .../level_zero/include/L0Device.h             |  4 +++
 .../level_zero/include/L0Plugin.h             |  4 +++
 .../level_zero/src/L0Context.cpp              |  2 +-
 .../level_zero/src/L0Device.cpp               | 14 ++------
 .../level_zero/src/L0Plugin.cpp               | 36 ++++++++++++++++---
 .../OffloadAPI/common/Properties.hpp          |  5 +++
 .../OffloadAPI/device/olGetDeviceInfo.cpp     | 13 +++++--
 .../OffloadAPI/device/olGetDeviceInfoSize.cpp | 12 ++++++-
 21 files changed, 183 insertions(+), 41 deletions(-)

diff --git a/libsycl/src/detail/device_impl.hpp b/libsycl/src/detail/device_impl.hpp
index f5012fe84c069..c057a07d2807d 100644
--- a/libsycl/src/detail/device_impl.hpp
+++ b/libsycl/src/detail/device_impl.hpp
@@ -44,7 +44,14 @@ class DeviceImpl {
   /// All device impls must be created in corresponding platform ctor.
   explicit DeviceImpl(ol_device_handle_t Device, PlatformImpl &Platform,
                       PrivateTag)
-      : MOffloadDevice(Device), MPlatform(Platform) {}
+      : MOffloadDevice(Device), MPlatform(Platform) {
+    ol_result_t Res =
+        callNoCheck(olGetDeviceInfo, MOffloadDevice,
+                    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
+                    sizeof(MContextGroupIndex), &MContextGroupIndex);
+    if (isFailed(Res))
+      MContextGroupIndex = 0;
+  }
 
   ~DeviceImpl() = default;
 
@@ -124,9 +131,13 @@ class DeviceImpl {
   /// \return the corresponding liboffload device handle.
   ol_device_handle_t getOLHandle() const { return MOffloadDevice; }
 
+  /// \return the context compatibility group this device belongs to.
+  uint32_t getContextGroupIndex() const { return MContextGroupIndex; }
+
 private:
   ol_device_handle_t MOffloadDevice = {};
   PlatformImpl &MPlatform;
+  uint32_t MContextGroupIndex = 0;
 };
 
 } // namespace detail
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index 1d81b848a21d3..3e3b3f338ac03 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -16,6 +16,7 @@
 #include <detail/platform_impl.hpp>
 
 #include <algorithm>
+#include <map>
 #include <memory>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
@@ -93,13 +94,16 @@ PlatformImpl::PlatformImpl(ol_platform_handle_t Platform, size_t PlatformIndex,
                       Device, *this, DeviceImpl::PrivateTag{}));
                 });
 
-  std::vector<DeviceImpl *> DeviceImpls;
-  DeviceImpls.reserve(MRootDevices.size());
+  std::map<uint32_t, std::vector<DeviceImpl *>> GroupedDevices;
   for (const auto &Device : MRootDevices)
-    DeviceImpls.push_back(Device.get());
+    GroupedDevices[Device->getContextGroupIndex()].push_back(Device.get());
 
-  MDefaultContext = ContextImpl::create(std::move(DeviceImpls),
-                                        defaultAsyncHandler, property_list{});
+  MDefaultContexts.reserve(GroupedDevices.size());
+  for (auto &[GroupIdx, DeviceImpls] : GroupedDevices) {
+    MDefaultContexts.push_back(
+        {GroupIdx, ContextImpl::create(std::move(DeviceImpls),
+                                       defaultAsyncHandler, property_list{})});
+  }
 }
 
 const std::vector<DeviceImplUPtr> &PlatformImpl::getRootDevices() const {
@@ -144,10 +148,18 @@ void PlatformImpl::iterateDevices(
   }
 }
 
-ContextImpl &PlatformImpl::getDefaultContext() {
-  assert(MDefaultContext &&
-         "Default context for platform must be created in platform ctor");
-  return *MDefaultContext.get();
+ContextImpl &PlatformImpl::getDefaultContext(const DeviceImpl &Device) {
+  assert(!MDefaultContexts.empty() &&
+         "Default contexts must be created in platform ctor");
+
+  uint32_t GroupIdx = Device.getContextGroupIndex();
+  for (auto &Entry : MDefaultContexts) {
+    if (Entry.ContextGroupIndex == GroupIdx)
+      return *Entry.Context;
+  }
+
+  assert(false && "No default context for device's context group");
+  __builtin_unreachable();
 }
 
 } // namespace detail
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index 83ad3453ab765..af253ca61f23d 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -132,11 +132,8 @@ class PlatformImpl {
   void iterateDevices(info::device_type DeviceType,
                       std::function<void(DeviceImpl *)> callback) const;
 
-  // TODO: liboffload doesn't support context now, l0 plugin creates default
-  // context for all devices on its level. This method should be removed or
-  // reimplemented once native context support is added to liboffload.
-  /// \return the default context that represents all devices in platform.
-  ContextImpl &getDefaultContext();
+  /// \return the default context compatible with Device.
+  ContextImpl &getDefaultContext(const DeviceImpl &Device);
 
 private:
   /// \return reference to collection of root devices for platform
@@ -150,7 +147,11 @@ class PlatformImpl {
 
   std::vector<DeviceImplUPtr> MRootDevices;
 
-  std::shared_ptr<ContextImpl> MDefaultContext;
+  struct DefaultContextEntry {
+    uint32_t ContextGroupIndex;
+    std::shared_ptr<ContextImpl> Context;
+  };
+  std::vector<DefaultContextEntry> MDefaultContexts;
 
   // Single initialization of platforms and devices doesn't allow to implement
   // unittests for this behavior. This flag and friend class allows to force
diff --git a/libsycl/src/detail/queue_impl.cpp b/libsycl/src/detail/queue_impl.cpp
index bd76f2aaa2a6e..10c9183df022a 100644
--- a/libsycl/src/detail/queue_impl.cpp
+++ b/libsycl/src/detail/queue_impl.cpp
@@ -66,7 +66,7 @@ QueueImpl::QueueImpl(DeviceImpl &deviceImpl, const async_handler &asyncHandler,
                      const property_list &propList, PrivateTag)
     : MIsInorder(false), MAsyncHandler(asyncHandler), MPropList(propList),
       MDevice(deviceImpl),
-      MContext(MDevice.getPlatformImpl().getDefaultContext()) {
+      MContext(MDevice.getPlatformImpl().getDefaultContext(MDevice)) {
   assert(MContext.getOLHandleRef() &&
          "Queue must be associated with a valid offload context");
   callAndThrow(olCreateQueue, MContext.getOLHandleRef(), MDevice.getOLHandle(),
diff --git a/libsycl/unittests/device_selector/get_device_preference.cpp b/libsycl/unittests/device_selector/get_device_preference.cpp
index 79920b9611a10..f3c162215d258 100644
--- a/libsycl/unittests/device_selector/get_device_preference.cpp
+++ b/libsycl/unittests/device_selector/get_device_preference.cpp
@@ -49,6 +49,16 @@ class DeviceSelectorScoreTest : public ::testing::Test {
           *static_cast<ol_platform_handle_t *>(PropValue) = Platform;
           return OL_SUCCESS;
         });
+
+    EXPECT_CALL(Helper.Mock.get(),
+                olGetDeviceInfo(_, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX, _, _))
+        .WillRepeatedly([](ol_device_handle_t /*Device*/,
+                           ol_device_info_t /*PropName*/, size_t PropSize,
+                           void *PropValue) -> ol_result_t {
+          EXPECT_EQ(PropSize, sizeof(uint32_t));
+          *static_cast<uint32_t *>(PropValue) = 0;
+          return OL_SUCCESS;
+        });
   }
 
   void TearDown() override {
diff --git a/libsycl/unittests/mock/helpers.cpp b/libsycl/unittests/mock/helpers.cpp
index f12e8509f1dce..091b8cfba2bb9 100644
--- a/libsycl/unittests/mock/helpers.cpp
+++ b/libsycl/unittests/mock/helpers.cpp
@@ -113,6 +113,11 @@ void mock::MockLiboffload::initDefault() {
           assignAs<ol_device_type_t>(PropValue, OL_DEVICE_TYPE_GPU);
           return OL_SUCCESS;
         }
+        case OL_DEVICE_INFO_CONTEXT_GROUP_INDEX: {
+          EXPECT_EQ(PropSize, sizeof(uint32_t));
+          assignAs<uint32_t>(PropValue, 0);
+          return OL_SUCCESS;
+        }
         default:
           ADD_FAILURE();
           return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
@@ -134,6 +139,10 @@ void mock::MockLiboffload::initDefault() {
           *PropSizeRet = sizeof(ol_device_type_t);
           return OL_SUCCESS;
         }
+        case OL_DEVICE_INFO_CONTEXT_GROUP_INDEX: {
+          *PropSizeRet = sizeof(uint32_t);
+          return OL_SUCCESS;
+        }
         default:
           ADD_FAILURE();
           return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
diff --git a/offload/liboffload/API/Context.td b/offload/liboffload/API/Context.td
index 1b407265cd879..02d38112eba25 100644
--- a/offload/liboffload/API/Context.td
+++ b/offload/liboffload/API/Context.td
@@ -13,7 +13,8 @@
 def olCreateContext : Function {
   let desc = "Create a context grouping the given devices.";
   let details = [
-    "All devices must belong to the same platform.",
+    "All devices must belong to the same platform and context group (as reported by "
+    "`OL_DEVICE_INFO_CONTEXT_GROUP_INDEX`). A context group typically corresponds to a driver instance.",
     "A context enables resource sharing between the devices it groups and "
     "isolates those resources from other contexts: resources (such as memory "
     "allocations) created within a context cannot be used outside of it.",
@@ -31,7 +32,7 @@ def olCreateContext : Function {
       "`DevicesCount == 0`"
     ]>,
     Return<"OL_ERRC_INVALID_DEVICE", [
-      "the devices in `Devices` do not all belong to the same platform"
+      "the devices in `Devices` do not all belong to the same context group"
     ]>
   ];
 }
diff --git a/offload/liboffload/API/Device.td b/offload/liboffload/API/Device.td
index cee053b1ff336..21c226784410f 100644
--- a/offload/liboffload/API/Device.td
+++ b/offload/liboffload/API/Device.td
@@ -57,6 +57,9 @@ def ol_device_info_t : Enum {
   list<TaggedEtor> basic_etors2 =
       [TaggedEtor<"COOPERATIVE_LAUNCH_SUPPORT", "bool",
                   "Is cooperative kernel launch supported">,
+       TaggedEtor<"CONTEXT_GROUP_INDEX", "uint32_t",
+                  "Context group index; devices with the same value can be "
+                  "grouped in a single context">,
   ];
   let etors = !listconcat(basic_etors, fp_configs, native_vec_widths,
                           fp_support, basic_etors2);
diff --git a/offload/liboffload/src/OffloadImpl.cpp b/offload/liboffload/src/OffloadImpl.cpp
index 48feac0b6c780..d4ecc78cb2caa 100644
--- a/offload/liboffload/src/OffloadImpl.cpp
+++ b/offload/liboffload/src/OffloadImpl.cpp
@@ -45,6 +45,7 @@ struct ol_platform_impl_t {
                      ol_platform_backend_t BackendType)
       : BackendType(BackendType), Plugin(std::move(Plugin)) {}
   ol_platform_backend_t BackendType;
+  uint32_t ContextGroupBase = 0;
 
   /// Complete all pending work for this platform and perform any needed
   /// cleanup.
@@ -77,6 +78,11 @@ struct ol_device_impl_t {
   InfoTreeNode Info;
 };
 
+static uint32_t getContextGroupIndex(ol_device_handle_t Device) {
+  return Device->Platform.ContextGroupBase +
+         Device->Device->getContextGroupOffset();
+}
+
 llvm::Error ol_platform_impl_t::destroy() { return Plugin->deinit(); }
 
 llvm::Error ol_platform_impl_t::init() {
@@ -333,6 +339,13 @@ Error initPlugins(OffloadContext &Context, const ol_init_args_t *InitArgs) {
       return Err;
   }
 
+  uint32_t CurCtxGroupBase = 0;
+  for (auto &Platform : Context.Platforms) {
+    Platform->ContextGroupBase = CurCtxGroupBase;
+    CurCtxGroupBase +=
+        Platform->Plugin ? Platform->Plugin->getNumContextGroups() : 1;
+  }
+
   Context.TracingEnabled = std::getenv("OFFLOAD_TRACE");
   Context.ValidationEnabled = !std::getenv("OFFLOAD_DISABLE_VALIDATION");
 
@@ -483,6 +496,9 @@ Error olGetDeviceInfoImplDetail(ol_device_handle_t Device,
     return Info.write<uint64_t>(Mem);
   } break;
 
+  case OL_DEVICE_INFO_CONTEXT_GROUP_INDEX:
+    return Info.write<uint32_t>(getContextGroupIndex(Device));
+
   default:
     break;
   }
@@ -626,6 +642,10 @@ Error olCreateContext_impl(size_t DevicesCount, ol_device_handle_t *Devices,
       return createOffloadError(
           ErrorCode::INVALID_DEVICE,
           "all devices in a context must belong to the same platform");
+    if (getContextGroupIndex(Devices[I]) != getContextGroupIndex(Devices[0]))
+      return createOffloadError(
+          ErrorCode::INVALID_DEVICE,
+          "all devices in a context must belong to the same context group");
     DeviceList.push_back(Devices[I]);
     PluginDevices.push_back(Devices[I]->Device);
   }
diff --git a/offload/plugins-nextgen/common/include/PluginInterface.h b/offload/plugins-nextgen/common/include/PluginInterface.h
index 30c79e28f2ea4..09cff34a1bd75 100644
--- a/offload/plugins-nextgen/common/include/PluginInterface.h
+++ b/offload/plugins-nextgen/common/include/PluginInterface.h
@@ -959,6 +959,9 @@ struct GenericDeviceTy : public DeviceAllocatorTy {
   /// this id is not unique between different plugins; they may overlap.
   int32_t getDeviceId() const { return DeviceId; }
 
+  /// Get the index of the context group this device belongs to.
+  virtual uint32_t getContextGroupOffset() const { return 0; }
+
   /// Get the unique identifier of the device.
   const char *getDeviceUid() const { return DeviceUid.c_str(); }
 
@@ -1547,6 +1550,9 @@ struct GenericPluginTy {
   /// Get the number of active devices.
   int32_t getNumDevices() const { return NumDevices; }
 
+  /// Get the number of context groups supported by this plugin.
+  virtual uint32_t getNumContextGroups() const { return 1; }
+
   /// Get the plugin-specific device identifier.
   int32_t getUserId(int32_t DeviceId) const {
     assert(UserDeviceIds.contains(DeviceId) && "No user-id registered");
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
index 55e4b6b856a96..758d3cb1406c3 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
@@ -57,6 +57,7 @@ DLWRAP(zeDeviceGetMemoryProperties, 3)
 DLWRAP(zeDeviceGetCacheProperties, 3)
 DLWRAP(zeDeviceGetGlobalTimestamps, 3)
 DLWRAP(zeDriverGetApiVersion, 2)
+DLWRAP(zeDriverGetProperties, 2)
 DLWRAP(zeDriverGetExtensionFunctionAddress, 3)
 DLWRAP(zeDriverGetExtensionProperties, 3)
 DLWRAP(zeEventCreate, 3)
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
index 4d8cf1e9367c0..2b760cfde4e12 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
@@ -334,11 +334,24 @@ typedef struct _ze_uuid_t {
   uint8_t id[16];
 } ze_uuid_t;
 
+/* Driver UUID size */
+#ifndef ZE_MAX_DRIVER_UUID_SIZE
+#define ZE_MAX_DRIVER_UUID_SIZE 16
+#endif
+
 /* Driver UUID */
 typedef struct _ze_driver_uuid_t {
-  ze_uuid_t id;
+  uint8_t id[ZE_MAX_DRIVER_UUID_SIZE];
 } ze_driver_uuid_t;
 
+/* Driver properties */
+typedef struct _ze_driver_properties_t {
+  ze_structure_type_t stype;
+  void *pNext;
+  ze_driver_uuid_t uuid;
+  uint32_t driverVersion;
+} ze_driver_properties_t;
+
 /* Device UUID */
 typedef struct _ze_device_uuid_t {
   ze_uuid_t id;
@@ -666,6 +679,8 @@ ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGet(uint32_t *pCount,
                                                 ze_driver_handle_t *phDrivers);
 ZE_APIEXPORT ze_result_t ZE_APICALL
 zeDriverGetApiVersion(ze_driver_handle_t hDriver, ze_api_version_t *version);
+ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetProperties(
+    ze_driver_handle_t hDriver, ze_driver_properties_t *pDriverProperties);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetExtensionFunctionAddress(
     ze_driver_handle_t hDriver, const char *name, void **ppFunctionAddress);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetExtensionProperties(
diff --git a/offload/plugins-nextgen/level_zero/include/L0Context.h b/offload/plugins-nextgen/level_zero/include/L0Context.h
index 09a19702baa23..ff4ee162c9f0b 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Context.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Context.h
@@ -50,6 +50,9 @@ class L0ContextTy {
   /// Level Zero Driver handle.
   ze_driver_handle_t zeDriver = nullptr;
 
+  /// Context group index within the Level Zero plugin.
+  uint32_t ContextGroupIdx;
+
   /// Common Level Zero context.
   ze_context_handle_t zeContext = nullptr;
 
@@ -122,6 +125,8 @@ class L0ContextTy {
 
   ze_driver_handle_t getZeDriver() const { return zeDriver; }
 
+  uint32_t getContextGroupIdx() const { return ContextGroupIdx; }
+
   /// Return context associated with the driver.
   ze_context_handle_t getZeContext() const { return zeContext; }
 
diff --git a/offload/plugins-nextgen/level_zero/include/L0Device.h b/offload/plugins-nextgen/level_zero/include/L0Device.h
index 84df2a2140446..5272dec2f02b4 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Device.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Device.h
@@ -185,6 +185,10 @@ class L0DeviceTy final : public GenericDeviceTy {
   Error deinitImpl() override;
   ze_device_handle_t getZeDevice() const { return zeDevice; }
 
+  uint32_t getContextGroupOffset() const override {
+    return L0Context.getContextGroupIdx();
+  }
+
   bool supportsCooperativeKernels() const {
     return QueueConfig.SupportsCooperativeKernels;
   }
diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index 82e47e052f339..81385ff5d0946 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -64,6 +64,8 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   struct DeviceInfoTy {
     L0DeviceIdTy Id;
     L0ContextTy *Driver;
+    uint32_t DriverVersion;
+    ze_driver_uuid_t DriverUuid;
     bool isRoot() const { return Id.SubId < 0 && Id.CCSId < 0; }
   };
   llvm::SmallVector<DeviceInfoTy> DetectedDevices;
@@ -111,6 +113,8 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   uint16_t getMagicElfBits() const override { return ELF::EM_INTELGT; }
   Triple::ArchType getTripleArch() const override { return Triple::spirv64; }
   const char *getName() const override { return GETNAME(TARGET_NAME); }
+  uint32_t getNumContextGroups() const override { return ContextList.size(); }
+  std::string getDriverVersion(int32_t DeviceId) const;
 
   Expected<bool> isELFCompatible(uint32_t DeviceId,
                                  StringRef Image) const override;
diff --git a/offload/plugins-nextgen/level_zero/src/L0Context.cpp b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
index cdcd1210cbcf1..62f4582469f9a 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Context.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Context.cpp
@@ -17,7 +17,7 @@ namespace llvm::omp::target::plugin {
 
 L0ContextTy::L0ContextTy(LevelZeroPluginTy &Plugin, ze_driver_handle_t zeDriver,
                          int32_t DriverId)
-    : Plugin(Plugin), zeDriver(zeDriver) {}
+    : Plugin(Plugin), zeDriver(zeDriver), ContextGroupIdx(DriverId) {}
 
 L0ContextTy::~L0ContextTy() = default;
 
diff --git a/offload/plugins-nextgen/level_zero/src/L0Device.cpp b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
index 08c45b534e16c..b09a3b4e49b13 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Device.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
@@ -428,12 +428,6 @@ const char *L0DeviceTy::getArchCStr() const {
   }
 }
 
-static const char *DriverVersionToStrTable[] = {
-    "1.0", "1.1", "1.2", "1.3",  "1.4",  "1.5", "1.6",
-    "1.7", "1.8", "1.9", "1.10", "1.11", "1.12"};
-constexpr size_t DriverVersionToStrTableSize =
-    sizeof(DriverVersionToStrTable) / sizeof(DriverVersionToStrTable[0]);
-
 Expected<InfoTreeNode> L0DeviceTy::obtainInfoImpl() {
   InfoTreeNode Info;
   Info.add("Device Number", getDeviceId());
@@ -442,12 +436,8 @@ Expected<InfoTreeNode> L0DeviceTy::obtainInfoImpl() {
   Info.add("Device Type", "GPU", "", DeviceInfo::TYPE);
   Info.add("Vendor", "Intel", "", DeviceInfo::VENDOR);
   Info.add("Vendor ID", getVendorId(), "", DeviceInfo::VENDOR_ID);
-  auto DriverVersion = getDriverAPIVersion();
-  if (DriverVersion < DriverVersionToStrTableSize)
-    Info.add("Driver Version", DriverVersionToStrTable[DriverVersion], "",
-             DeviceInfo::DRIVER_VERSION);
-  else
-    Info.add("Driver Version", "Unknown", "", DeviceInfo::DRIVER_VERSION);
+  Info.add("Driver Version", getPlugin().getDriverVersion(getDeviceId()), "",
+           DeviceInfo::DRIVER_VERSION);
   Info.add("Device PCI ID", getPCIId());
   Info.add("Device UUID", getUuid().data());
   Info.add("Number of total EUs", getNumEUs(), "",
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index a8c3e522c36ba..fbbce836e7e3c 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -55,6 +55,8 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
     uint32_t OrderId;
     ze_device_handle_t ZeDevice;
     L0ContextTy *Driver;
+    uint32_t DriverVersion;
+    ze_driver_uuid_t DriverUuid;
     bool IsDiscrete;
   };
   llvm::SmallVector<RootInfoTy> RootDevices;
@@ -70,8 +72,15 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
                       << ".";
       continue;
     }
+
+    ze_driver_properties_t DriverProperties{};
+    DriverProperties.stype = ZE_STRUCTURE_TYPE_DRIVER_PROPERTIES;
+    DriverProperties.pNext = nullptr;
+    CALL_ZE_RET_ERROR(zeDriverGetProperties, Driver, &DriverProperties);
+
     // We have a driver that supports at least one device.
-    ContextList.emplace_back(*this, Driver, DriverId);
+    ContextList.emplace_back(*this, Driver,
+                             static_cast<int32_t>(ContextList.size()));
     auto &DrvInfo = ContextList.back();
     if (auto Err = DrvInfo.init()) {
       // Remove the partially initialized context from the list
@@ -83,7 +92,8 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
 
     for (auto &zeDevice : FoundDevices)
       RootDevices.push_back(
-          {OrderId++, zeDevice, &DrvInfo, L0DeviceTy::isDiscrete(zeDevice)});
+          {OrderId++, zeDevice, &DrvInfo, DriverProperties.driverVersion,
+           DriverProperties.uuid, L0DeviceTy::isDiscrete(zeDevice)});
   }
 
   // Move discrete devices to the front.
@@ -103,8 +113,13 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
   for (size_t RootId = 0; RootId < RootDevices.size(); RootId++) {
     const auto ZeDevice = RootDevices[RootId].ZeDevice;
     auto *RootDriver = RootDevices[RootId].Driver;
-    DetectedDevices.push_back(DeviceInfoTy{
-        {ZeDevice, static_cast<int32_t>(RootId), -1, -1}, RootDriver});
+    auto DriverVersion = RootDevices[RootId].DriverVersion;
+    auto DriverUuid = RootDevices[RootId].DriverUuid;
+    DetectedDevices.push_back(
+        DeviceInfoTy{{ZeDevice, static_cast<int32_t>(RootId), -1, -1},
+                     RootDriver,
+                     DriverVersion,
+                     DriverUuid});
   }
   int32_t NumDevices = DetectedDevices.size();
 
@@ -124,6 +139,19 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
   return NumDevices;
 }
 
+std::string LevelZeroPluginTy::getDriverVersion(int32_t DeviceId) const {
+  assert(DeviceId >= 0 &&
+         static_cast<size_t>(DeviceId) < DetectedDevices.size());
+  const auto &DeviceInfo = DetectedDevices[DeviceId];
+
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << DeviceInfo.DriverVersion << " (";
+  OS.write_uuid(DeviceInfo.DriverUuid.id);
+  OS << ")";
+  return OS.str();
+}
+
 Expected<int32_t> LevelZeroPluginTy::initImpl() {
   ODBG(OLDT_Init) << "Level0 NG plugin initialization";
   // Process options before anything else.
diff --git a/offload/unittests/OffloadAPI/common/Properties.hpp b/offload/unittests/OffloadAPI/common/Properties.hpp
index 849f4ea05f29a..3be2bfe9dab21 100644
--- a/offload/unittests/OffloadAPI/common/Properties.hpp
+++ b/offload/unittests/OffloadAPI/common/Properties.hpp
@@ -98,6 +98,11 @@ inline const DeviceInfoProp PropUint32{
 inline const DeviceInfoProperties Uint32Properties =
     createPropertiesWithSizeContainer(sizeof(uint32_t), PropUint32);
 
+inline const DeviceInfoProp PropContextGroupIndex{
+    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX};
+inline const DeviceInfoProperties ContextGroupIndexProperties =
+    createPropertiesWithSizeContainer(sizeof(uint32_t), PropContextGroupIndex);
+
 inline const DeviceInfoProp PropUint64{
     OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE, OL_DEVICE_INFO_GLOBAL_MEM_SIZE,
     OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE};
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
index 18882c5af4818..e34749f111e0f 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
@@ -10,9 +10,9 @@
 #include <OffloadAPI.h>
 #include <gtest/gtest.h>
 
-DeviceInfoProperties JustSupportedProperties =
-    mergeProperties({BoolProperties, IrrelevantForHostGTCapabilitiesProperties,
-                     IrrelevantForHostGTUint32Properties});
+DeviceInfoProperties JustSupportedProperties = mergeProperties(
+    {BoolProperties, IrrelevantForHostGTCapabilitiesProperties,
+     IrrelevantForHostGTUint32Properties, ContextGroupIndexProperties});
 
 DeviceInfoProperties NonZeroProperties =
     mergeProperties({RelevantGTCapabilitiesProperties,
@@ -91,6 +91,13 @@ TEST_P(olGetHostDeviceInfoTest, SuccessPlatform) {
   ASSERT_NE(Platform, nullptr);
 }
 
+TEST_P(olGetHostDeviceInfoTest, SuccessContextGroupIndex) {
+  uint32_t ContextGroupIndex = 0;
+  ASSERT_SUCCESS(olGetDeviceInfo(Device, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
+                                 sizeof(ContextGroupIndex),
+                                 &ContextGroupIndex));
+}
+
 TEST_P(olGetHostDeviceInfoTest, InvalidNullHandleDevice) {
   ol_device_type_t DeviceType;
   ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
index 82e0d36f027d9..4d7811ec8e64e 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
@@ -17,7 +17,7 @@ using olGetDeviceInfoSizeNonZeroTest = olGetHostDeviceInfoPropertyTest;
 
 DeviceInfoProperties answerSizeEqualToTypeSizeProperties = mergeProperties(
     {Uint32Properties, Uint64Properties, CapabilitesFlagsProperties,
-     PlatformProperties, DeviceTypeProperties});
+     PlatformProperties, DeviceTypeProperties, ContextGroupIndexProperties});
 
 OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE_WITH_PARAM(
     olGetDeviceInfoSizeEqualTest, answerSizeEqualToTypeSizeProperties,
@@ -55,6 +55,16 @@ TEST_P(olGetDeviceInfoSizeTest, SuccessMaxWorkSizePerDimension) {
   ASSERT_EQ(Size, sizeof(uint32_t) * 3);
 }
 
+TEST(olGetDeviceInfoSizeHostTest, SuccessContextGroupIndex) {
+  ol_device_handle_t Host = TestEnvironment::getHostDevice();
+  ASSERT_NE(Host, nullptr);
+
+  size_t Size = 0;
+  ASSERT_SUCCESS(
+      olGetDeviceInfoSize(Host, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX, &Size));
+  ASSERT_EQ(Size, sizeof(uint32_t));
+}
+
 TEST_P(olGetDeviceInfoSizeTest, InvalidNullHandle) {
   size_t Size = 0;
   ASSERT_ERROR(OL_ERRC_INVALID_NULL_HANDLE,

>From ba8c223c2f6759fede398de66da8d6878770931f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Thu, 20 Aug 2026 09:42:43 +0000
Subject: [PATCH 2/7] run clang-format

---
 libsycl/src/detail/device_impl.hpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libsycl/src/detail/device_impl.hpp b/libsycl/src/detail/device_impl.hpp
index c057a07d2807d..9ec7acebfa305 100644
--- a/libsycl/src/detail/device_impl.hpp
+++ b/libsycl/src/detail/device_impl.hpp
@@ -45,10 +45,9 @@ class DeviceImpl {
   explicit DeviceImpl(ol_device_handle_t Device, PlatformImpl &Platform,
                       PrivateTag)
       : MOffloadDevice(Device), MPlatform(Platform) {
-    ol_result_t Res =
-        callNoCheck(olGetDeviceInfo, MOffloadDevice,
-                    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
-                    sizeof(MContextGroupIndex), &MContextGroupIndex);
+    ol_result_t Res = callNoCheck(
+        olGetDeviceInfo, MOffloadDevice, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
+        sizeof(MContextGroupIndex), &MContextGroupIndex);
     if (isFailed(Res))
       MContextGroupIndex = 0;
   }

>From d6efe7e4f298a76b359a58df5ba47b3877d9bc6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Thu, 20 Aug 2026 11:08:23 +0000
Subject: [PATCH 3/7] create SYCL platform for each context group

---
 libsycl/src/detail/device_impl.hpp            |  12 +-
 .../src/detail/offload/offload_topology.cpp   |  59 +++-----
 .../src/detail/offload/offload_topology.hpp   |  58 +++----
 libsycl/src/detail/platform_impl.cpp          |  80 +++-------
 libsycl/src/detail/platform_impl.hpp          |  27 +---
 libsycl/src/detail/queue_impl.cpp             |  10 +-
 libsycl/unittests/common/unittests_helper.hpp |  17 ++-
 libsycl/unittests/platform/get_platforms.cpp  | 143 ++++++++++++++++++
 8 files changed, 235 insertions(+), 171 deletions(-)

diff --git a/libsycl/src/detail/device_impl.hpp b/libsycl/src/detail/device_impl.hpp
index 9ec7acebfa305..f5012fe84c069 100644
--- a/libsycl/src/detail/device_impl.hpp
+++ b/libsycl/src/detail/device_impl.hpp
@@ -44,13 +44,7 @@ class DeviceImpl {
   /// All device impls must be created in corresponding platform ctor.
   explicit DeviceImpl(ol_device_handle_t Device, PlatformImpl &Platform,
                       PrivateTag)
-      : MOffloadDevice(Device), MPlatform(Platform) {
-    ol_result_t Res = callNoCheck(
-        olGetDeviceInfo, MOffloadDevice, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
-        sizeof(MContextGroupIndex), &MContextGroupIndex);
-    if (isFailed(Res))
-      MContextGroupIndex = 0;
-  }
+      : MOffloadDevice(Device), MPlatform(Platform) {}
 
   ~DeviceImpl() = default;
 
@@ -130,13 +124,9 @@ class DeviceImpl {
   /// \return the corresponding liboffload device handle.
   ol_device_handle_t getOLHandle() const { return MOffloadDevice; }
 
-  /// \return the context compatibility group this device belongs to.
-  uint32_t getContextGroupIndex() const { return MContextGroupIndex; }
-
 private:
   ol_device_handle_t MOffloadDevice = {};
   PlatformImpl &MPlatform;
-  uint32_t MContextGroupIndex = 0;
 };
 
 } // namespace detail
diff --git a/libsycl/src/detail/offload/offload_topology.cpp b/libsycl/src/detail/offload/offload_topology.cpp
index c04024eef48c5..25e8e49a86758 100644
--- a/libsycl/src/detail/offload/offload_topology.cpp
+++ b/libsycl/src/detail/offload/offload_topology.cpp
@@ -10,54 +10,31 @@
 #include <detail/offload/offload_topology.hpp>
 #include <detail/offload/offload_utils.hpp>
 
+#include <algorithm>
 #include <array>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-// Platforms for this backend
-range_view<const ol_platform_handle_t> OffloadTopology::getPlatforms() const {
-  return {MPlatforms.data(), MPlatforms.size()};
-}
-
-// Devices for a specific platform (PlatformId is index into Platforms)
-range_view<ol_device_handle_t>
-OffloadTopology::getDevices(size_t PlatformId) const {
-  if (PlatformId >= MDeviceRange.size()) {
-    return {nullptr, 0};
-  }
-  return MDeviceRange[PlatformId];
-}
-
 void OffloadTopology::registerNewPlatformsAndDevices(
-    Platform2DevContainer &PlatformsAndDev) {
-  if (!PlatformsAndDev.size())
-    return;
-
-  // MDeviceRange is populated with iterators of MDevices. Allocate required
-  // space in advance to keep them valid.
-  MDevices.reserve(PlatformsAndDev.size());
-
-  for (auto &[Platform, NewDev] : PlatformsAndDev) {
-    MDevices.push_back(NewDev);
-
-    // Platform is not unique within PlatformsAndDev but the container is sorted
-    if (MPlatforms.empty() || MPlatforms.back() != Platform) {
-      MPlatforms.push_back(Platform);
-      range_view<ol_device_handle_t> R{&MDevices.back(), 1 /*Size == 1*/};
-      MDeviceRange.push_back(R);
-    } else {
-      // Device is inserted already, just increment device count for the current
-      // platform
-      MDeviceRange.back().len++;
+    const Platform2DevContainer &PlatformsAndDev) {
+  for (const OffloadDeviceDesc &Entry : PlatformsAndDev) {
+    auto GroupIt = std::find_if(MPlatformGroups.begin(), MPlatformGroups.end(),
+                                [&](const OffloadPlatformGroup &Group) {
+                                  return Group.Platform == Entry.Platform &&
+                                         Group.ContextGroupIndex ==
+                                             Entry.ContextGroupIndex;
+                                });
+    if (GroupIt == MPlatformGroups.end()) {
+      MPlatformGroups.push_back({Entry.Platform, Entry.ContextGroupIndex, {}});
+      GroupIt = MPlatformGroups.end() - 1;
     }
+    GroupIt->Devices.push_back(Entry.Device);
   }
 }
 
 void discoverOffloadDevices() {
-  // liboffload returns devices sorted by backend + platform. We rely on this
-  // behavior during device enumeration.
   using PerBackendDataType =
       std::array<Platform2DevContainer, OL_PLATFORM_BACKEND_LAST>;
 
@@ -96,7 +73,15 @@ void discoverOffloadDevices() {
         if (OlBackend >= OL_PLATFORM_BACKEND_LAST)
           return true;
 
-        (*Data)[static_cast<size_t>(OlBackend)].push_back({Platform, Dev});
+        uint32_t ContextGroupIndex = 0;
+        Res = callNoCheck(olGetDeviceInfo, Dev,
+                          OL_DEVICE_INFO_CONTEXT_GROUP_INDEX,
+                          sizeof(ContextGroupIndex), &ContextGroupIndex);
+        if (Res != OL_SUCCESS)
+          ContextGroupIndex = 0;
+
+        (*Data)[static_cast<size_t>(OlBackend)].push_back(
+            {Platform, Dev, ContextGroupIndex});
         return true;
       },
       &Mapping);
diff --git a/libsycl/src/detail/offload/offload_topology.hpp b/libsycl/src/detail/offload/offload_topology.hpp
index f8634a19de31e..107f02d47234a 100644
--- a/libsycl/src/detail/offload/offload_topology.hpp
+++ b/libsycl/src/detail/offload/offload_topology.hpp
@@ -19,28 +19,28 @@
 
 #include <OffloadAPI.h>
 
-#include <cassert>
+#include <cstdint>
 #include <vector>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
 
 namespace detail {
 
-// Minimal span-like view.
-template <class T> struct range_view {
-  T *ptr{};
-  size_t len{};
-  T *begin() const { return ptr; }
-  T *end() const { return ptr + len; }
-  T &operator[](size_t i) const { return ptr[i]; }
-  size_t size() const { return len; }
+struct OffloadDeviceDesc {
+  ol_platform_handle_t Platform;
+  ol_device_handle_t Device;
+  uint32_t ContextGroupIndex;
 };
 
-using Platform2DevContainer =
-    std::vector<std::pair<ol_platform_handle_t, ol_device_handle_t>>;
+using Platform2DevContainer = std::vector<OffloadDeviceDesc>;
 
-/// Contiguous global storage of platform handlers and device handles (grouped
-/// by platform) for a backend.
+struct OffloadPlatformGroup {
+  ol_platform_handle_t Platform;
+  uint32_t ContextGroupIndex;
+  std::vector<ol_device_handle_t> Devices;
+};
+
+/// Storage of platform context groups and their device handles for a backend.
 struct OffloadTopology {
   OffloadTopology() : MBackend(OL_PLATFORM_BACKEND_UNKNOWN) {}
   OffloadTopology(ol_platform_backend_t OlBackend) : MBackend(OlBackend) {}
@@ -55,37 +55,23 @@ struct OffloadTopology {
   /// \returns backend of this topology.
   ol_platform_backend_t getBackend() const { return MBackend; }
 
-  /// Returns all platforms associated with this topology.
+  /// Returns all platform context groups associated with this topology.
   ///
-  /// \returns minimal span-like view to platforms associated with this
-  /// topology.
-  range_view<const ol_platform_handle_t> getPlatforms() const;
+  /// \returns platform context groups associated with this topology.
+  const std::vector<OffloadPlatformGroup> &getPlatformGroups() const {
+    return MPlatformGroups;
+  }
 
-  /// Returns all devices associated with specific platform.
-  ///
-  /// \param PlatformId is index into MPlatforms.
-  ///
-  /// \returns minimal span-like view to devices associated with specified
-  /// platform.
-  range_view<ol_device_handle_t> getDevices(size_t PlatformId) const;
-
-  /// Register new platform and devices into this topology.
+  /// Registers platform context groups and devices into this topology.
   ///
   /// \param PlatformsAndDev collection of platforms & devices.
-  void registerNewPlatformsAndDevices(Platform2DevContainer &PlatformsAndDev);
+  void
+  registerNewPlatformsAndDevices(const Platform2DevContainer &PlatformsAndDev);
 
 private:
   ol_platform_backend_t MBackend = OL_PLATFORM_BACKEND_UNKNOWN;
 
-  // Platforms and devices belonging to this backend (flattened)
-  std::vector<ol_platform_handle_t> MPlatforms;
-
-  // Devices are sorted by platform (guarantee from liboffload)
-  std::vector<ol_device_handle_t> MDevices;
-
-  // Vector holding range of devices for each platform (index is platform index
-  // within Platforms), so MDeviceRange.size() == MPlatforms.size()
-  std::vector<range_view<ol_device_handle_t>> MDeviceRange;
+  std::vector<OffloadPlatformGroup> MPlatformGroups;
 };
 
 // Initialize the topologies by calling olIterateDevices.
diff --git a/libsycl/src/detail/platform_impl.cpp b/libsycl/src/detail/platform_impl.cpp
index 3e3b3f338ac03..3e09741a9d6c8 100644
--- a/libsycl/src/detail/platform_impl.cpp
+++ b/libsycl/src/detail/platform_impl.cpp
@@ -16,7 +16,6 @@
 #include <detail/platform_impl.hpp>
 
 #include <algorithm>
-#include <map>
 #include <memory>
 
 _LIBSYCL_BEGIN_NAMESPACE_SYCL
@@ -25,20 +24,6 @@ namespace detail {
 
 bool PlatformImpl::rediscoverIfEmpty = false;
 
-PlatformImpl &PlatformImpl::getPlatformImpl(ol_platform_handle_t Platform) {
-  auto &PlatformCache = getPlatformCache();
-  for (auto &PlatImpl : PlatformCache) {
-    assert(PlatImpl && "Platform impl can not be nullptr");
-    if (PlatImpl->getOLHandleRef() == Platform)
-      return *PlatImpl;
-  }
-
-  throw sycl::exception(
-      sycl::make_error_code(sycl::errc::runtime),
-      "Platform for requested handle can't be created. This handle is not in "
-      "the list of platforms discovered by liboffload");
-}
-
 const std::vector<PlatformImplUPtr> &PlatformImpl::getPlatforms() {
   static auto InitPlatforms = []() {
     discoverOffloadDevices();
@@ -49,10 +34,9 @@ const std::vector<PlatformImplUPtr> &PlatformImpl::getPlatforms() {
     for (const auto &Topo : getOffloadTopologies()) {
       if (Topo.getBackend() == OL_PLATFORM_BACKEND_HOST)
         continue;
-      size_t PlatformIndex = 0;
-      for (const auto &OffloadPlatform : Topo.getPlatforms()) {
+      for (const auto &PlatformGroup : Topo.getPlatformGroups()) {
         PlatformCache.emplace_back(std::make_unique<PlatformImpl>(
-            OffloadPlatform, PlatformIndex++, PrivateTag{}));
+            PlatformGroup.Platform, PlatformGroup.Devices, PrivateTag{}));
       }
     }
   };
@@ -69,41 +53,30 @@ const std::vector<PlatformImplUPtr> &PlatformImpl::getPlatforms() {
   return PlatformCache;
 }
 
-PlatformImpl::PlatformImpl(ol_platform_handle_t Platform, size_t PlatformIndex,
+PlatformImpl::PlatformImpl(ol_platform_handle_t Platform,
+                           const std::vector<ol_device_handle_t> &Devices,
                            PrivateTag)
-    : MOffloadPlatform(Platform), MOffloadPlatformIndex(PlatformIndex) {
+    : MOffloadPlatform(Platform) {
+  assert(!Devices.empty() && "Platform must contain at least one device");
+
   ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN;
   callAndThrow(olGetPlatformInfo, MOffloadPlatform, OL_PLATFORM_INFO_BACKEND,
                sizeof(Backend), &Backend);
   MBackend = convertBackend(Backend);
-  MOffloadBackend = Backend;
-
-  const auto &Topologies = getOffloadTopologies();
-  auto RootTopologyIt = std::find_if(
-      Topologies.begin(), Topologies.end(), [&](const OffloadTopology &Topo) {
-        return Topo.getBackend() == MOffloadBackend;
-      });
-
-  assert(RootTopologyIt != Topologies.end() &&
-         "Root topology for platform must always exist");
-  auto DevRange = RootTopologyIt->getDevices(MOffloadPlatformIndex);
-  MRootDevices.reserve(DevRange.size());
-  std::for_each(DevRange.begin(), DevRange.end(),
-                [&](const ol_device_handle_t &Device) {
-                  MRootDevices.emplace_back(std::make_unique<DeviceImpl>(
-                      Device, *this, DeviceImpl::PrivateTag{}));
-                });
-
-  std::map<uint32_t, std::vector<DeviceImpl *>> GroupedDevices;
-  for (const auto &Device : MRootDevices)
-    GroupedDevices[Device->getContextGroupIndex()].push_back(Device.get());
 
-  MDefaultContexts.reserve(GroupedDevices.size());
-  for (auto &[GroupIdx, DeviceImpls] : GroupedDevices) {
-    MDefaultContexts.push_back(
-        {GroupIdx, ContextImpl::create(std::move(DeviceImpls),
-                                       defaultAsyncHandler, property_list{})});
+  MRootDevices.reserve(Devices.size());
+  for (const ol_device_handle_t &Device : Devices) {
+    MRootDevices.emplace_back(
+        std::make_unique<DeviceImpl>(Device, *this, DeviceImpl::PrivateTag{}));
   }
+
+  std::vector<DeviceImpl *> DeviceImpls;
+  DeviceImpls.reserve(MRootDevices.size());
+  for (const auto &Device : MRootDevices)
+    DeviceImpls.push_back(Device.get());
+
+  MDefaultContext = ContextImpl::create(std::move(DeviceImpls),
+                                        defaultAsyncHandler, property_list{});
 }
 
 const std::vector<DeviceImplUPtr> &PlatformImpl::getRootDevices() const {
@@ -148,18 +121,9 @@ void PlatformImpl::iterateDevices(
   }
 }
 
-ContextImpl &PlatformImpl::getDefaultContext(const DeviceImpl &Device) {
-  assert(!MDefaultContexts.empty() &&
-         "Default contexts must be created in platform ctor");
-
-  uint32_t GroupIdx = Device.getContextGroupIndex();
-  for (auto &Entry : MDefaultContexts) {
-    if (Entry.ContextGroupIndex == GroupIdx)
-      return *Entry.Context;
-  }
-
-  assert(false && "No default context for device's context group");
-  __builtin_unreachable();
+ContextImpl &PlatformImpl::getDefaultContext() {
+  assert(MDefaultContext && "Default context must be created in platform ctor");
+  return *MDefaultContext;
 }
 
 } // namespace detail
diff --git a/libsycl/src/detail/platform_impl.hpp b/libsycl/src/detail/platform_impl.hpp
index af253ca61f23d..5926403f96b1e 100644
--- a/libsycl/src/detail/platform_impl.hpp
+++ b/libsycl/src/detail/platform_impl.hpp
@@ -56,10 +56,10 @@ class PlatformImpl {
   /// Constructs PlatformImpl from a platform handle.
   ///
   /// \param Platform is a raw offload library handle representing platform.
-  /// \param PlatformIndex is a platform index in a backend (needed for a proper
-  /// indexing in device selector).
+  /// \param Devices are the devices in one platform context group.
   /// All platform impls are created during first getPlatforms() call.
-  PlatformImpl(ol_platform_handle_t Platform, size_t PlatformIndex, PrivateTag);
+  PlatformImpl(ol_platform_handle_t Platform,
+               const std::vector<ol_device_handle_t> &Devices, PrivateTag);
 
   ~PlatformImpl() = default;
 
@@ -83,15 +83,6 @@ class PlatformImpl {
     return MOffloadPlatform;
   }
 
-  /// Queries the cache to get the implementation for specified offloading RT
-  /// platform. All platform implementation objects are created at first
-  /// get_platforms call.
-  ///
-  /// \param Platform is the offloading RT Platform handle representing the
-  /// platform.
-  /// \return the PlatformImpl representing the offloading RT platform.
-  static PlatformImpl &getPlatformImpl(ol_platform_handle_t Platform);
-
   /// Indicates if all of the SYCL devices on this platform have the
   /// given aspect.
   ///
@@ -132,26 +123,20 @@ class PlatformImpl {
   void iterateDevices(info::device_type DeviceType,
                       std::function<void(DeviceImpl *)> callback) const;
 
-  /// \return the default context compatible with Device.
-  ContextImpl &getDefaultContext(const DeviceImpl &Device);
+  /// \return the default context containing all devices in this platform.
+  ContextImpl &getDefaultContext();
 
 private:
   /// \return reference to collection of root devices for platform
   const std::vector<DeviceImplUPtr> &getRootDevices() const;
 
   const ol_platform_handle_t MOffloadPlatform{};
-  const size_t MOffloadPlatformIndex{};
 
-  ol_platform_backend_t MOffloadBackend{OL_PLATFORM_BACKEND_UNKNOWN};
   backend MBackend{};
 
   std::vector<DeviceImplUPtr> MRootDevices;
 
-  struct DefaultContextEntry {
-    uint32_t ContextGroupIndex;
-    std::shared_ptr<ContextImpl> Context;
-  };
-  std::vector<DefaultContextEntry> MDefaultContexts;
+  std::shared_ptr<ContextImpl> MDefaultContext;
 
   // Single initialization of platforms and devices doesn't allow to implement
   // unittests for this behavior. This flag and friend class allows to force
diff --git a/libsycl/src/detail/queue_impl.cpp b/libsycl/src/detail/queue_impl.cpp
index a184c49e497b3..df004a5cc0e1a 100644
--- a/libsycl/src/detail/queue_impl.cpp
+++ b/libsycl/src/detail/queue_impl.cpp
@@ -66,7 +66,7 @@ QueueImpl::QueueImpl(DeviceImpl &deviceImpl, const async_handler &asyncHandler,
                      const property_list &propList, PrivateTag)
     : MIsInorder(false), MAsyncHandler(asyncHandler), MPropList(propList),
       MDevice(deviceImpl),
-      MContext(MDevice.getPlatformImpl().getDefaultContext(MDevice)) {
+      MContext(MDevice.getPlatformImpl().getDefaultContext()) {
   assert(MContext.getOLHandleRef() &&
          "Queue must be associated with a valid offload context");
   callAndThrow(olCreateQueue, MContext.getOLHandleRef(), MDevice.getOLHandle(),
@@ -82,8 +82,14 @@ QueueImpl::~QueueImpl() {
 backend QueueImpl::getBackend() const noexcept { return MDevice.getBackend(); }
 
 static ol_device_handle_t getHostOLDevice() {
+  const auto &HostPlatformGroups =
+      getOffloadTopologies()[OL_PLATFORM_BACKEND_HOST].getPlatformGroups();
+  assert(!HostPlatformGroups.empty() &&
+         "Host platform must contain at least one context group");
+  assert(!HostPlatformGroups.front().Devices.empty() &&
+         "Host platform context group must contain at least one device");
   static ol_device_handle_t HostDevice =
-      *(getOffloadTopologies()[OL_PLATFORM_BACKEND_HOST].getDevices(0).begin());
+      HostPlatformGroups.front().Devices.front();
   return HostDevice;
 }
 
diff --git a/libsycl/unittests/common/unittests_helper.hpp b/libsycl/unittests/common/unittests_helper.hpp
index a04995225f0e5..c2cffac2375f5 100644
--- a/libsycl/unittests/common/unittests_helper.hpp
+++ b/libsycl/unittests/common/unittests_helper.hpp
@@ -29,15 +29,20 @@ namespace unittests {
 // allows to call global state reset and platforms initialization methods to be
 // able to set expectations on devices enumeration calls in a proper way.
 struct UnittestsHelper {
-  UnittestsHelper() { detail::PlatformImpl::rediscoverIfEmpty = true; }
+  UnittestsHelper() {
+    resetPlatformState();
+    detail::PlatformImpl::rediscoverIfEmpty = true;
+  }
+
+  ~UnittestsHelper() { resetPlatformState(); }
 
-  ~UnittestsHelper() {
-    if (!detail::getPlatformCache().empty()) {
-      detail::getPlatformCache().clear();
-      detail::getOffloadTopologies() = {};
-    }
+private:
+  static void resetPlatformState() {
+    detail::getPlatformCache().clear();
+    detail::getOffloadTopologies() = {};
   }
 
+public:
   mock::MockWrapper Mock;
 };
 
diff --git a/libsycl/unittests/platform/get_platforms.cpp b/libsycl/unittests/platform/get_platforms.cpp
index 16a701d481f24..1b0f5bb3f3ef0 100644
--- a/libsycl/unittests/platform/get_platforms.cpp
+++ b/libsycl/unittests/platform/get_platforms.cpp
@@ -6,13 +6,25 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include <common/unittests_helper.hpp>
+
+#include <detail/platform_impl.hpp>
+#include <sycl/__impl/detail/obj_utils.hpp>
 #include <sycl/sycl.hpp>
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include <array>
+#include <cstdint>
+#include <tuple>
+
 using namespace sycl;
+using namespace ::testing;
 
 TEST(PlatformTest, APIGetPlatformsDefaultMock) {
+  unittests::UnittestsHelper Helper;
+
   auto Platforms = sycl::platform::get_platforms();
   ASSERT_EQ(Platforms.size(), 1u);
   EXPECT_EQ(Platforms[0].get_backend(), sycl::backend::level_zero);
@@ -36,3 +48,134 @@ TEST(PlatformTest, APIGetPlatformsDefaultMock) {
   ASSERT_EQ(CtxDevices[0], Devices[0]);
 #endif
 }
+
+namespace {
+
+class PlatformContextGroupTest : public Test {
+protected:
+  void SetUp() override {
+    Platform = mock::createDummyHandle<ol_platform_handle_t>();
+    for (ol_device_handle_t &Device : Devices) {
+      Device = mock::createDummyHandleWithData<ol_device_handle_t>(
+          reinterpret_cast<unsigned char *>(&Platform), sizeof(Platform));
+    }
+
+    EXPECT_CALL(Helper.Mock.get(), olIterateDevices(_, _))
+        .WillRepeatedly([this](ol_device_iterate_cb_t Callback,
+                               void *UserData) -> ol_result_t {
+          for (ol_device_handle_t Device : Devices)
+            std::ignore = Callback(Device, UserData);
+          return OL_SUCCESS;
+        });
+
+    ON_CALL(Helper.Mock.get(),
+            olGetDeviceInfo(_, OL_DEVICE_INFO_CONTEXT_GROUP_INDEX, _, _))
+        .WillByDefault([this](ol_device_handle_t Device,
+                              ol_device_info_t /*PropName*/, size_t PropSize,
+                              void *PropValue) -> ol_result_t {
+          EXPECT_EQ(PropSize, sizeof(uint32_t));
+          if (FailContextGroupQuery)
+            return Helper.Mock.get().makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+
+          *static_cast<uint32_t *>(PropValue) = getContextGroup(Device);
+          return OL_SUCCESS;
+        });
+  }
+
+  void TearDown() override {
+    detail::getPlatformCache().clear();
+    detail::getOffloadTopologies() = {};
+    mock::releaseDummyHandles(Devices[0], Devices[1], Devices[2], Platform);
+  }
+
+  uint32_t getContextGroup(ol_device_handle_t Device) const {
+    if (Device == Devices[0] || Device == Devices[2])
+      return 0;
+    if (Device == Devices[1])
+      return 1;
+    ADD_FAILURE() << "Unexpected device";
+    return 0;
+  }
+
+  unittests::UnittestsHelper Helper;
+  ol_platform_handle_t Platform{};
+  std::array<ol_device_handle_t, 3> Devices{};
+  bool FailContextGroupQuery = false;
+};
+
+TEST_F(PlatformContextGroupTest, CreatesPlatformForEachContextGroup) {
+  EXPECT_CALL(Helper.Mock.get(), olCreateContext(_, _, _))
+      .Times(2)
+      .WillRepeatedly([this](size_t NumDevices,
+                             ol_device_handle_t *ContextDevices,
+                             ol_context_handle_t *Context) -> ol_result_t {
+        EXPECT_GT(NumDevices, 0u);
+        if (NumDevices == 0)
+          return Helper.Mock.get().makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+        const uint32_t ContextGroup = getContextGroup(ContextDevices[0]);
+        for (size_t I = 1; I < NumDevices; ++I)
+          EXPECT_EQ(getContextGroup(ContextDevices[I]), ContextGroup);
+
+        *Context = mock::createDummyHandleWithData<ol_context_handle_t>(
+            reinterpret_cast<unsigned char *>(&ContextDevices[0]),
+            sizeof(ContextDevices[0]));
+        return OL_SUCCESS;
+      });
+
+  auto Platforms = sycl::platform::get_platforms();
+  ASSERT_EQ(Platforms.size(), 2u);
+  EXPECT_NE(Platforms[0], Platforms[1]);
+
+  auto Platform0Devices = Platforms[0].get_devices();
+  ASSERT_EQ(Platform0Devices.size(), 2u);
+  EXPECT_EQ(detail::getSyclObjImpl(Platform0Devices[0])->getOLHandle(),
+            Devices[0]);
+  EXPECT_EQ(detail::getSyclObjImpl(Platform0Devices[1])->getOLHandle(),
+            Devices[2]);
+
+  auto Platform1Devices = Platforms[1].get_devices();
+  ASSERT_EQ(Platform1Devices.size(), 1u);
+  EXPECT_EQ(detail::getSyclObjImpl(Platform1Devices[0])->getOLHandle(),
+            Devices[1]);
+
+  EXPECT_EQ(Platform0Devices[0].get_platform(), Platforms[0]);
+  EXPECT_EQ(Platform0Devices[1].get_platform(), Platforms[0]);
+  EXPECT_EQ(Platform1Devices[0].get_platform(), Platforms[1]);
+
+  EXPECT_EQ(detail::getSyclObjImpl(Platforms[0])->getOLHandleRef(), Platform);
+  EXPECT_EQ(detail::getSyclObjImpl(Platforms[1])->getOLHandleRef(), Platform);
+
+  context Context0 = Platforms[0].khr_get_default_context();
+  context Context1 = Platforms[1].khr_get_default_context();
+  EXPECT_EQ(Context0.get_platform(), Platforms[0]);
+  EXPECT_EQ(Context1.get_platform(), Platforms[1]);
+  EXPECT_EQ(Context0.get_devices(), Platform0Devices);
+  EXPECT_EQ(Context1.get_devices(), Platform1Devices);
+
+  queue Queue0{Platform0Devices[0]};
+  queue Queue1{Platform1Devices[0]};
+  EXPECT_EQ(Queue0.get_context(), Context0);
+  EXPECT_EQ(Queue1.get_context(), Context1);
+}
+
+TEST_F(PlatformContextGroupTest, ContextGroupQueryFailureUsesDefaultGroup) {
+  FailContextGroupQuery = true;
+
+  EXPECT_CALL(Helper.Mock.get(), olCreateContext(3, _, _)).Times(1);
+
+  auto Platforms = sycl::platform::get_platforms();
+  ASSERT_EQ(Platforms.size(), 1u);
+
+  auto PlatformDevices = Platforms[0].get_devices();
+  ASSERT_EQ(PlatformDevices.size(), Devices.size());
+  EXPECT_EQ(detail::getSyclObjImpl(PlatformDevices[0])->getOLHandle(),
+            Devices[0]);
+  EXPECT_EQ(detail::getSyclObjImpl(PlatformDevices[1])->getOLHandle(),
+            Devices[1]);
+  EXPECT_EQ(detail::getSyclObjImpl(PlatformDevices[2])->getOLHandle(),
+            Devices[2]);
+  EXPECT_EQ(Platforms[0].khr_get_default_context().get_devices(),
+            PlatformDevices);
+}
+
+} // namespace

>From ebad6f9f14f8d02294d91de85f563a376a064e15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Mon, 24 Aug 2026 09:01:06 +0000
Subject: [PATCH 4/7] prettify olIterateDevices UserData access in
 discoverOffloadDevices

---
 libsycl/src/detail/offload/offload_topology.cpp | 5 +++--
 libsycl/unittests/platform/get_platforms.cpp    | 2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libsycl/src/detail/offload/offload_topology.cpp b/libsycl/src/detail/offload/offload_topology.cpp
index 25e8e49a86758..e833cc5fbcf3f 100644
--- a/libsycl/src/detail/offload/offload_topology.cpp
+++ b/libsycl/src/detail/offload/offload_topology.cpp
@@ -80,8 +80,9 @@ void discoverOffloadDevices() {
         if (Res != OL_SUCCESS)
           ContextGroupIndex = 0;
 
-        (*Data)[static_cast<size_t>(OlBackend)].push_back(
-            {Platform, Dev, ContextGroupIndex});
+        auto BackendIndex = static_cast<size_t>(OlBackend);
+        auto &DeviceDescVec = (*Data)[BackendIndex];
+        DeviceDescVec.push_back({Platform, Dev, ContextGroupIndex});
         return true;
       },
       &Mapping);
diff --git a/libsycl/unittests/platform/get_platforms.cpp b/libsycl/unittests/platform/get_platforms.cpp
index 1b0f5bb3f3ef0..ec362a6cc97e3 100644
--- a/libsycl/unittests/platform/get_platforms.cpp
+++ b/libsycl/unittests/platform/get_platforms.cpp
@@ -17,7 +17,7 @@
 
 #include <array>
 #include <cstdint>
-#include <tuple>
+// #include <tuple>
 
 using namespace sycl;
 using namespace ::testing;

>From d8057ead811677185de73daa352f80d4f9a8d949 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Mon, 24 Aug 2026 09:24:39 +0000
Subject: [PATCH 5/7] revert driver info changes

---
 .../level_zero/dynamic_l0/L0DynWrapper.cpp    |  1 -
 .../level_zero/dynamic_l0/level_zero/ze_api.h | 17 +---------
 .../level_zero/include/L0Plugin.h             |  3 --
 .../level_zero/src/L0Device.cpp               | 14 ++++++--
 .../level_zero/src/L0Plugin.cpp               | 32 ++-----------------
 5 files changed, 16 insertions(+), 51 deletions(-)

diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
index 758d3cb1406c3..55e4b6b856a96 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/L0DynWrapper.cpp
@@ -57,7 +57,6 @@ DLWRAP(zeDeviceGetMemoryProperties, 3)
 DLWRAP(zeDeviceGetCacheProperties, 3)
 DLWRAP(zeDeviceGetGlobalTimestamps, 3)
 DLWRAP(zeDriverGetApiVersion, 2)
-DLWRAP(zeDriverGetProperties, 2)
 DLWRAP(zeDriverGetExtensionFunctionAddress, 3)
 DLWRAP(zeDriverGetExtensionProperties, 3)
 DLWRAP(zeEventCreate, 3)
diff --git a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
index 2b760cfde4e12..4d8cf1e9367c0 100644
--- a/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
+++ b/offload/plugins-nextgen/level_zero/dynamic_l0/level_zero/ze_api.h
@@ -334,24 +334,11 @@ typedef struct _ze_uuid_t {
   uint8_t id[16];
 } ze_uuid_t;
 
-/* Driver UUID size */
-#ifndef ZE_MAX_DRIVER_UUID_SIZE
-#define ZE_MAX_DRIVER_UUID_SIZE 16
-#endif
-
 /* Driver UUID */
 typedef struct _ze_driver_uuid_t {
-  uint8_t id[ZE_MAX_DRIVER_UUID_SIZE];
+  ze_uuid_t id;
 } ze_driver_uuid_t;
 
-/* Driver properties */
-typedef struct _ze_driver_properties_t {
-  ze_structure_type_t stype;
-  void *pNext;
-  ze_driver_uuid_t uuid;
-  uint32_t driverVersion;
-} ze_driver_properties_t;
-
 /* Device UUID */
 typedef struct _ze_device_uuid_t {
   ze_uuid_t id;
@@ -679,8 +666,6 @@ ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGet(uint32_t *pCount,
                                                 ze_driver_handle_t *phDrivers);
 ZE_APIEXPORT ze_result_t ZE_APICALL
 zeDriverGetApiVersion(ze_driver_handle_t hDriver, ze_api_version_t *version);
-ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetProperties(
-    ze_driver_handle_t hDriver, ze_driver_properties_t *pDriverProperties);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetExtensionFunctionAddress(
     ze_driver_handle_t hDriver, const char *name, void **ppFunctionAddress);
 ZE_APIEXPORT ze_result_t ZE_APICALL zeDriverGetExtensionProperties(
diff --git a/offload/plugins-nextgen/level_zero/include/L0Plugin.h b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
index 81385ff5d0946..35d5ad29f1b25 100644
--- a/offload/plugins-nextgen/level_zero/include/L0Plugin.h
+++ b/offload/plugins-nextgen/level_zero/include/L0Plugin.h
@@ -64,8 +64,6 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   struct DeviceInfoTy {
     L0DeviceIdTy Id;
     L0ContextTy *Driver;
-    uint32_t DriverVersion;
-    ze_driver_uuid_t DriverUuid;
     bool isRoot() const { return Id.SubId < 0 && Id.CCSId < 0; }
   };
   llvm::SmallVector<DeviceInfoTy> DetectedDevices;
@@ -114,7 +112,6 @@ class LevelZeroPluginTy final : public GenericPluginTy {
   Triple::ArchType getTripleArch() const override { return Triple::spirv64; }
   const char *getName() const override { return GETNAME(TARGET_NAME); }
   uint32_t getNumContextGroups() const override { return ContextList.size(); }
-  std::string getDriverVersion(int32_t DeviceId) const;
 
   Expected<bool> isELFCompatible(uint32_t DeviceId,
                                  StringRef Image) const override;
diff --git a/offload/plugins-nextgen/level_zero/src/L0Device.cpp b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
index b09a3b4e49b13..08c45b534e16c 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Device.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Device.cpp
@@ -428,6 +428,12 @@ const char *L0DeviceTy::getArchCStr() const {
   }
 }
 
+static const char *DriverVersionToStrTable[] = {
+    "1.0", "1.1", "1.2", "1.3",  "1.4",  "1.5", "1.6",
+    "1.7", "1.8", "1.9", "1.10", "1.11", "1.12"};
+constexpr size_t DriverVersionToStrTableSize =
+    sizeof(DriverVersionToStrTable) / sizeof(DriverVersionToStrTable[0]);
+
 Expected<InfoTreeNode> L0DeviceTy::obtainInfoImpl() {
   InfoTreeNode Info;
   Info.add("Device Number", getDeviceId());
@@ -436,8 +442,12 @@ Expected<InfoTreeNode> L0DeviceTy::obtainInfoImpl() {
   Info.add("Device Type", "GPU", "", DeviceInfo::TYPE);
   Info.add("Vendor", "Intel", "", DeviceInfo::VENDOR);
   Info.add("Vendor ID", getVendorId(), "", DeviceInfo::VENDOR_ID);
-  Info.add("Driver Version", getPlugin().getDriverVersion(getDeviceId()), "",
-           DeviceInfo::DRIVER_VERSION);
+  auto DriverVersion = getDriverAPIVersion();
+  if (DriverVersion < DriverVersionToStrTableSize)
+    Info.add("Driver Version", DriverVersionToStrTable[DriverVersion], "",
+             DeviceInfo::DRIVER_VERSION);
+  else
+    Info.add("Driver Version", "Unknown", "", DeviceInfo::DRIVER_VERSION);
   Info.add("Device PCI ID", getPCIId());
   Info.add("Device UUID", getUuid().data());
   Info.add("Number of total EUs", getNumEUs(), "",
diff --git a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
index fbbce836e7e3c..9f797c0778e8c 100644
--- a/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
+++ b/offload/plugins-nextgen/level_zero/src/L0Plugin.cpp
@@ -55,8 +55,6 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
     uint32_t OrderId;
     ze_device_handle_t ZeDevice;
     L0ContextTy *Driver;
-    uint32_t DriverVersion;
-    ze_driver_uuid_t DriverUuid;
     bool IsDiscrete;
   };
   llvm::SmallVector<RootInfoTy> RootDevices;
@@ -73,11 +71,6 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
       continue;
     }
 
-    ze_driver_properties_t DriverProperties{};
-    DriverProperties.stype = ZE_STRUCTURE_TYPE_DRIVER_PROPERTIES;
-    DriverProperties.pNext = nullptr;
-    CALL_ZE_RET_ERROR(zeDriverGetProperties, Driver, &DriverProperties);
-
     // We have a driver that supports at least one device.
     ContextList.emplace_back(*this, Driver,
                              static_cast<int32_t>(ContextList.size()));
@@ -92,8 +85,7 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
 
     for (auto &zeDevice : FoundDevices)
       RootDevices.push_back(
-          {OrderId++, zeDevice, &DrvInfo, DriverProperties.driverVersion,
-           DriverProperties.uuid, L0DeviceTy::isDiscrete(zeDevice)});
+          {OrderId++, zeDevice, &DrvInfo, L0DeviceTy::isDiscrete(zeDevice)});
   }
 
   // Move discrete devices to the front.
@@ -113,13 +105,8 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
   for (size_t RootId = 0; RootId < RootDevices.size(); RootId++) {
     const auto ZeDevice = RootDevices[RootId].ZeDevice;
     auto *RootDriver = RootDevices[RootId].Driver;
-    auto DriverVersion = RootDevices[RootId].DriverVersion;
-    auto DriverUuid = RootDevices[RootId].DriverUuid;
-    DetectedDevices.push_back(
-        DeviceInfoTy{{ZeDevice, static_cast<int32_t>(RootId), -1, -1},
-                     RootDriver,
-                     DriverVersion,
-                     DriverUuid});
+    DetectedDevices.push_back(DeviceInfoTy{
+        {ZeDevice, static_cast<int32_t>(RootId), -1, -1}, RootDriver});
   }
   int32_t NumDevices = DetectedDevices.size();
 
@@ -139,19 +126,6 @@ Expected<int32_t> LevelZeroPluginTy::findDevices() {
   return NumDevices;
 }
 
-std::string LevelZeroPluginTy::getDriverVersion(int32_t DeviceId) const {
-  assert(DeviceId >= 0 &&
-         static_cast<size_t>(DeviceId) < DetectedDevices.size());
-  const auto &DeviceInfo = DetectedDevices[DeviceId];
-
-  std::string Result;
-  llvm::raw_string_ostream OS(Result);
-  OS << DeviceInfo.DriverVersion << " (";
-  OS.write_uuid(DeviceInfo.DriverUuid.id);
-  OS << ")";
-  return OS.str();
-}
-
 Expected<int32_t> LevelZeroPluginTy::initImpl() {
   ODBG(OLDT_Init) << "Level0 NG plugin initialization";
   // Process options before anything else.

>From c539f48949f843e55f7da3152d6bcca4eeecb355 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Mon, 24 Aug 2026 10:52:15 +0000
Subject: [PATCH 6/7] add OL_DEVICE_INFO_CONTEXT_GROUP_INDEX to PropUint32

---
 offload/unittests/OffloadAPI/common/Properties.hpp   | 12 +++++-------
 .../unittests/OffloadAPI/device/olGetDeviceInfo.cpp  |  2 +-
 .../OffloadAPI/device/olGetDeviceInfoSize.cpp        |  2 +-
 3 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/offload/unittests/OffloadAPI/common/Properties.hpp b/offload/unittests/OffloadAPI/common/Properties.hpp
index 3be2bfe9dab21..9b2bd68fb331d 100644
--- a/offload/unittests/OffloadAPI/common/Properties.hpp
+++ b/offload/unittests/OffloadAPI/common/Properties.hpp
@@ -94,15 +94,12 @@ inline const DeviceInfoProp PropUint32{
     OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY,
     OL_DEVICE_INFO_MEMORY_CLOCK_RATE,
     OL_DEVICE_INFO_ADDRESS_BITS,
-    OL_DEVICE_INFO_NUM_LANES};
+    OL_DEVICE_INFO_NUM_LANES,
+    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX};
+
 inline const DeviceInfoProperties Uint32Properties =
     createPropertiesWithSizeContainer(sizeof(uint32_t), PropUint32);
 
-inline const DeviceInfoProp PropContextGroupIndex{
-    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX};
-inline const DeviceInfoProperties ContextGroupIndexProperties =
-    createPropertiesWithSizeContainer(sizeof(uint32_t), PropContextGroupIndex);
-
 inline const DeviceInfoProp PropUint64{
     OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE, OL_DEVICE_INFO_GLOBAL_MEM_SIZE,
     OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE};
@@ -131,7 +128,8 @@ inline const DeviceInfoProperties RelevantGTCapabilitiesProperties =
                                       Prop_RelevantGTCapabilites);
 
 inline const DeviceInfoProp PropIrrelevantForHostGTUint32 = {
-    OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF};
+    OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF,
+    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX}; 
 inline const DeviceInfoProperties IrrelevantForHostGTUint32Properties =
     createPropertiesWithSizeContainer(sizeof(uint32_t),
                                       PropIrrelevantForHostGTUint32);
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
index e34749f111e0f..49bdbb3d29ed2 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
@@ -12,7 +12,7 @@
 
 DeviceInfoProperties JustSupportedProperties = mergeProperties(
     {BoolProperties, IrrelevantForHostGTCapabilitiesProperties,
-     IrrelevantForHostGTUint32Properties, ContextGroupIndexProperties});
+     IrrelevantForHostGTUint32Properties});
 
 DeviceInfoProperties NonZeroProperties =
     mergeProperties({RelevantGTCapabilitiesProperties,
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
index 4d7811ec8e64e..fdf7792ceacf4 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfoSize.cpp
@@ -17,7 +17,7 @@ using olGetDeviceInfoSizeNonZeroTest = olGetHostDeviceInfoPropertyTest;
 
 DeviceInfoProperties answerSizeEqualToTypeSizeProperties = mergeProperties(
     {Uint32Properties, Uint64Properties, CapabilitesFlagsProperties,
-     PlatformProperties, DeviceTypeProperties, ContextGroupIndexProperties});
+     PlatformProperties, DeviceTypeProperties});
 
 OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE_WITH_PARAM(
     olGetDeviceInfoSizeEqualTest, answerSizeEqualToTypeSizeProperties,

>From 7741a98c7bf470b25a16c1c22eefc5471fdd66f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Trusi=C5=82=C5=82o?= <jan.trusillo at intel.com>
Date: Mon, 24 Aug 2026 10:52:50 +0000
Subject: [PATCH 7/7] run clang-format

---
 offload/unittests/OffloadAPI/common/Properties.hpp      | 2 +-
 offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/offload/unittests/OffloadAPI/common/Properties.hpp b/offload/unittests/OffloadAPI/common/Properties.hpp
index 9b2bd68fb331d..d0686ff331a4a 100644
--- a/offload/unittests/OffloadAPI/common/Properties.hpp
+++ b/offload/unittests/OffloadAPI/common/Properties.hpp
@@ -129,7 +129,7 @@ inline const DeviceInfoProperties RelevantGTCapabilitiesProperties =
 
 inline const DeviceInfoProp PropIrrelevantForHostGTUint32 = {
     OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF,
-    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX}; 
+    OL_DEVICE_INFO_CONTEXT_GROUP_INDEX};
 inline const DeviceInfoProperties IrrelevantForHostGTUint32Properties =
     createPropertiesWithSizeContainer(sizeof(uint32_t),
                                       PropIrrelevantForHostGTUint32);
diff --git a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
index 49bdbb3d29ed2..ef1fdf79bfbfa 100644
--- a/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
+++ b/offload/unittests/OffloadAPI/device/olGetDeviceInfo.cpp
@@ -10,9 +10,9 @@
 #include <OffloadAPI.h>
 #include <gtest/gtest.h>
 
-DeviceInfoProperties JustSupportedProperties = mergeProperties(
-    {BoolProperties, IrrelevantForHostGTCapabilitiesProperties,
-     IrrelevantForHostGTUint32Properties});
+DeviceInfoProperties JustSupportedProperties =
+    mergeProperties({BoolProperties, IrrelevantForHostGTCapabilitiesProperties,
+                     IrrelevantForHostGTUint32Properties});
 
 DeviceInfoProperties NonZeroProperties =
     mergeProperties({RelevantGTCapabilitiesProperties,



More information about the llvm-commits mailing list