@@ -252,4 +252,75 @@ TEST_F(InitDriverUnitTest, zeInitDriversWithAllTypes_VerifyRoutingToCorrectDrive
252252 // At least one type of driver should be found if we have drivers
253253 EXPECT_TRUE (foundGPUDriver || foundNPUDriver);
254254 }
255+ }
256+
257+ // Derived fixture for the NPU-loss regression test so it runs as its own
258+ // named test suite and can be targeted independently via --gtest_filter.
259+ class InitDriverGPUNPURegressionTest : public InitDriverUnitTest {};
260+
261+ // Regression test for the bug where calling zeInitDrivers with GPU-only flags
262+ // causes the NPU driver to be absent in a subsequent NPU|GPU call.
263+ //
264+ // Reproduction sequence:
265+ // Step 1: NPU|GPU → count=N (GPU + NPU) [expected: success]
266+ // Step 2: GPU → count=1 (GPU only) [expected: success]
267+ // Step 3: NPU → count=1 (NPU only) [expected: success]
268+ // Step 4: NPU|GPU → count should still equal N [BUG: count was < N]
269+ TEST_F (InitDriverGPUNPURegressionTest, zeInitDriversGPUAndNPU_AfterGPUOnlyThenNPUOnly_BothStillReturnedOnCombined) {
270+ ze_init_driver_type_desc_t descBoth = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
271+ descBoth.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU | ZE_INIT_DRIVER_TYPE_FLAG_NPU;
272+ descBoth.pNext = nullptr ;
273+
274+ ze_init_driver_type_desc_t descGPU = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
275+ descGPU.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU;
276+ descGPU.pNext = nullptr ;
277+
278+ ze_init_driver_type_desc_t descNPU = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
279+ descNPU.flags = ZE_INIT_DRIVER_TYPE_FLAG_NPU;
280+ descNPU.pNext = nullptr ;
281+
282+ // Step 1: NPU|GPU — establish the baseline combined count
283+ uint32_t countBothFirst = 0 ;
284+ ASSERT_EQ (ZE_RESULT_SUCCESS, zeInitDrivers (&countBothFirst, nullptr , &descBoth));
285+
286+ // Only meaningful if at least one driver is present
287+ if (countBothFirst == 0 ) {
288+ GTEST_SKIP () << " No GPU or NPU drivers available; skipping regression test" ;
289+ }
290+
291+ EXPECT_EQ (countBothFirst, 2 );
292+
293+ // Step 2: GPU-only call
294+ uint32_t countGPU = 0 ;
295+ EXPECT_EQ (ZE_RESULT_SUCCESS, zeInitDrivers (&countGPU, nullptr , &descGPU));
296+
297+ EXPECT_EQ (countGPU, 1 );
298+
299+ // Step 3: NPU-only call
300+ uint32_t countNPU = 0 ;
301+ EXPECT_EQ (ZE_RESULT_SUCCESS, zeInitDrivers (&countNPU, nullptr , &descNPU));
302+
303+ EXPECT_EQ (countNPU, 1 );
304+
305+ // Step 4: NPU|GPU again — must return the same count as Step 1
306+ // This is the regression check: the NPU driver must not have been lost
307+ // as a side-effect of the intermediate GPU-only or NPU-only calls.
308+ uint32_t countBothSecond = 0 ;
309+ EXPECT_EQ (ZE_RESULT_SUCCESS, zeInitDrivers (&countBothSecond, nullptr , &descBoth));
310+ EXPECT_EQ (countBothFirst, countBothSecond)
311+ << " Regression: zeInitDrivers(NPU|GPU) returned fewer drivers after "
312+ " intermediate GPU-only and NPU-only calls. "
313+ " First combined count=" << countBothFirst
314+ << " , second combined count=" << countBothSecond;
315+
316+ // Verify the returned handles are valid
317+ if (countBothSecond > 0 ) {
318+ std::vector<ze_driver_handle_t > drivers (countBothSecond);
319+ EXPECT_EQ (ZE_RESULT_SUCCESS, zeInitDrivers (&countBothSecond, drivers.data (), &descBoth));
320+ for (uint32_t i = 0 ; i < countBothSecond; i++) {
321+ EXPECT_NE (drivers[i], nullptr );
322+ uint32_t deviceCount = 0 ;
323+ EXPECT_EQ (ZE_RESULT_SUCCESS, zeDeviceGet (drivers[i], &deviceCount, nullptr ));
324+ }
325+ }
255326}
0 commit comments