Skip to content

Commit 6cce104

Browse files
committed
[L0] Implement Support for zeInitDrivers
- As of v1.10 of the L0 spec, zeInit and zeDriverGet is the old init pathway and the desired init api is zeInitDrivers. This new api allows for multi heterogenous drivers to coexist in a single L0 Process. Signed-off-by: Neil R. Spruit <[email protected]>
1 parent 9a209aa commit 6cce104

File tree

4 files changed

+136
-24
lines changed

4 files changed

+136
-24
lines changed

.github/workflows/build-fuzz-reusable.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
4242
- name: Build level zero with gcc
4343
run: |
44-
git clone -b v1.17.6 --depth=1 https://github.com/oneapi-src/level-zero.git ${{github.workspace}}/level-zero
44+
git clone -b v1.18.5 --depth=1 https://github.com/oneapi-src/level-zero.git ${{github.workspace}}/level-zero
4545
cd ${{github.workspace}}/level-zero
4646
cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
4747
cmake --build build -j $(nproc)

cmake/FetchLevelZero.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ if (NOT DEFINED LEVEL_ZERO_LIBRARY OR NOT DEFINED LEVEL_ZERO_INCLUDE_DIR)
4040
set(UR_LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git")
4141
endif()
4242
if (UR_LEVEL_ZERO_LOADER_TAG STREQUAL "")
43-
set(UR_LEVEL_ZERO_LOADER_TAG v1.18.5)
43+
set(UR_LEVEL_ZERO_LOADER_TAG ea296eb72e760b9c04b93e008063ce95cdfe6488)
4444
endif()
4545

4646
# Disable due to a bug https://github.com/oneapi-src/level-zero/issues/104

source/adapters/level_zero/adapter.cpp

Lines changed: 126 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,90 @@ ur_result_t getZesDeviceHandle(zes_uuid_t coreDeviceUuid,
7676
return UR_RESULT_ERROR_INVALID_ARGUMENT;
7777
}
7878

79+
/**
80+
* @brief Initializes the platforms by querying Level Zero drivers and devices.
81+
*
82+
* This function initializes the platforms by querying the available Level Zero
83+
* drivers and devices. It handles different behaviors based on the presence of
84+
* drivers obtained through `zeDriverGet` and initialized drivers through
85+
* `zeInitDrivers`.
86+
*
87+
* @param platforms A vector to store the initialized platform handles.
88+
* @param ZesResult The result of a previous ZES (Level Zero System) operation.
89+
* @return ur_result_t The result of the initialization process.
90+
*
91+
* The function performs the following steps:
92+
* 1. Queries the number of Level Zero drivers using `zeDriverGet`.
93+
* 2. If drivers are found, it retrieves their handles.
94+
* 3. If no drivers are found in either `zeInitDrivers` or `zeDriverGet`,
95+
* it logs a message and returns success.
96+
* 4. If `zeInitDrivers` is supported by the global adapter, it retrieves
97+
* their handles and properties.
98+
* 5. It compares the drivers obtained from `zeDriverGet` and `zeInitDrivers`,
99+
* adding unique drivers to the list.
100+
* 6. If `zeInitDrivers` is not supported, it uses the drivers obtained
101+
* from `zeDriverGet`.
102+
* 7. For each driver, it queries the devices and checks if they are GPU
103+
* devices.
104+
* 8. If a GPU device is found, it initializes a platform for the driver and
105+
* adds it to the platforms vector.
106+
* 9. If ZES operations are successful, it populates the ZES/ZE device mapping
107+
* for the devices into the platform.
108+
* 10. The function handles exceptions and returns the appropriate result.
109+
*/
79110
ur_result_t initPlatforms(PlatformVec &platforms,
80111
ze_result_t ZesResult) noexcept try {
112+
std::vector<ze_driver_handle_t> ZeDrivers;
113+
std::vector<ze_driver_handle_t> ZeDriverGetHandles;
114+
std::vector<ze_driver_handle_t> ZeInitDriversHandles;
115+
std::vector<ze_device_handle_t> ZeDevices;
81116
uint32_t ZeDriverCount = 0;
82-
ZE2UR_CALL(zeDriverGet, (&ZeDriverCount, nullptr));
83-
if (ZeDriverCount == 0) {
117+
uint32_t ZeDriverGetCount = 0;
118+
119+
auto ZeDriverGetResult =
120+
ZE_CALL_NOCHECK(zeDriverGet, (&ZeDriverGetCount, nullptr));
121+
if (ZeDriverGetCount > 0 && ZeDriverGetResult == ZE_RESULT_SUCCESS) {
122+
ZeDriverGetHandles.resize(ZeDriverGetCount);
123+
ZE2UR_CALL(zeDriverGet, (&ZeDriverGetCount, ZeDriverGetHandles.data()));
124+
}
125+
if (ZeDriverGetCount == 0 && GlobalAdapter->ZeInitDriversCount == 0) {
126+
logger::debug("\nNo Valid L0 Drivers found.\n");
84127
return UR_RESULT_SUCCESS;
85128
}
86129

87-
std::vector<ze_driver_handle_t> ZeDrivers;
88-
std::vector<ze_device_handle_t> ZeDevices;
89-
ZeDrivers.resize(ZeDriverCount);
90-
91-
ZE2UR_CALL(zeDriverGet, (&ZeDriverCount, ZeDrivers.data()));
130+
if (GlobalAdapter->InitDriversSupported) {
131+
ZE2UR_CALL(GlobalAdapter->initDriversFunctionPtr,
132+
(&GlobalAdapter->ZeInitDriversCount, ZeInitDriversHandles.data(),
133+
&GlobalAdapter->InitDriversDesc));
134+
ZeInitDriversHandles.resize(GlobalAdapter->ZeInitDriversCount);
135+
ZeDrivers.resize(GlobalAdapter->ZeInitDriversCount);
136+
ZeDrivers.assign(ZeInitDriversHandles.begin(), ZeInitDriversHandles.end());
137+
if (ZeDriverGetCount > 0 && GlobalAdapter->ZeInitDriversCount > 0) {
138+
for (uint32_t X = 0; X < GlobalAdapter->ZeInitDriversCount; ++X) {
139+
for (uint32_t Y = 0; Y < ZeDriverGetCount; ++Y) {
140+
ZeStruct<ze_driver_properties_t> ZeDriverGetProperties;
141+
ZeStruct<ze_driver_properties_t> ZeInitDriverProperties;
142+
ZE2UR_CALL(zeDriverGetProperties,
143+
(ZeDriverGetHandles[Y], &ZeDriverGetProperties));
144+
ZE2UR_CALL(zeDriverGetProperties,
145+
(ZeInitDriversHandles[X], &ZeInitDriverProperties));
146+
// If zeDriverGet driver is different from zeInitDriver driver, add it
147+
// to the list. This allows for older drivers to be used alongside
148+
// newer drivers.
149+
if (ZeDriverGetProperties.uuid.id != ZeInitDriverProperties.uuid.id) {
150+
logger::debug("\nzeDriverHandle {} added to the zeInitDrivers list "
151+
"of possible handles.\n",
152+
ZeDriverGetHandles[Y]);
153+
ZeDrivers.push_back(ZeDriverGetHandles[Y]);
154+
}
155+
}
156+
}
157+
}
158+
} else {
159+
ZeDriverCount = ZeDriverGetCount;
160+
ZeDrivers.resize(ZeDriverCount);
161+
ZeDrivers.assign(ZeDriverGetHandles.begin(), ZeDriverGetHandles.end());
162+
}
92163
for (uint32_t I = 0; I < ZeDriverCount; ++I) {
93164
// Keep track of the first platform init for this Driver
94165
bool DriverPlatformInit = false;
@@ -214,6 +285,15 @@ ur_adapter_handle_t_::ur_adapter_handle_t_()
214285
return std::atoi(UrRet);
215286
}();
216287

288+
// Dynamically load the new L0 apis separately.
289+
// This must be done to avoid attempting to use symbols that do
290+
// not exist in older loader runtimes.
291+
#ifdef _WIN32
292+
HMODULE processHandle = GetModuleHandle(NULL);
293+
#else
294+
HMODULE processHandle = nullptr;
295+
#endif
296+
217297
// initialize level zero only once.
218298
if (GlobalAdapter->ZeResult == std::nullopt) {
219299
// Setting these environment variables before running zeInit will enable
@@ -235,20 +315,52 @@ ur_adapter_handle_t_::ur_adapter_handle_t_()
235315
// called multiple times. Declaring the return value as "static" ensures
236316
// it's only called once.
237317

318+
GlobalAdapter->initDriversFunctionPtr =
319+
(ze_pfnInitDrivers_t)ur_loader::LibLoader::getFunctionPtr(
320+
processHandle, "zeInitDrivers");
321+
322+
// Set ZES_ENABLE_SYSMAN by default if the user has not set it.
323+
if (UrSysManEnvInitEnabled) {
324+
setEnvVar("ZES_ENABLE_SYSMAN", "1");
325+
}
326+
238327
// Init with all flags set to enable for all driver types to be init in
239328
// the application.
240329
ze_init_flags_t L0InitFlags = ZE_INIT_FLAG_GPU_ONLY;
241330
if (UrL0InitAllDrivers) {
242331
L0InitFlags |= ZE_INIT_FLAG_VPU_ONLY;
243332
}
244-
245-
// Set ZES_ENABLE_SYSMAN by default if the user has not set it.
246-
if (UrSysManEnvInitEnabled) {
247-
setEnvVar("ZES_ENABLE_SYSMAN", "1");
248-
}
249333
logger::debug("\nzeInit with flags value of {}\n",
250334
static_cast<int>(L0InitFlags));
251-
GlobalAdapter->ZeResult = ZE_CALL_NOCHECK(zeInit, (L0InitFlags));
335+
GlobalAdapter->ZeInitResult = ZE_CALL_NOCHECK(zeInit, (L0InitFlags));
336+
if (*GlobalAdapter->ZeInitResult != ZE_RESULT_SUCCESS) {
337+
logger::debug("\nzeInit failed with {}\n",
338+
*GlobalAdapter->ZeInitResult);
339+
}
340+
341+
if (GlobalAdapter->initDriversFunctionPtr) {
342+
GlobalAdapter->InitDriversDesc.pNext = nullptr;
343+
GlobalAdapter->InitDriversDesc.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU;
344+
logger::debug("\nzeInitDrivers with flags value of {}\n",
345+
static_cast<int>(GlobalAdapter->InitDriversDesc.flags));
346+
GlobalAdapter->ZeInitDriversResult =
347+
ZE_CALL_NOCHECK(GlobalAdapter->initDriversFunctionPtr,
348+
(&GlobalAdapter->ZeInitDriversCount, nullptr,
349+
&GlobalAdapter->InitDriversDesc));
350+
if (*GlobalAdapter->ZeInitDriversResult == ZE_RESULT_SUCCESS) {
351+
GlobalAdapter->InitDriversSupported = true;
352+
} else {
353+
logger::debug("\nzeInitDrivers failed with {}\n",
354+
*GlobalAdapter->ZeInitDriversResult);
355+
}
356+
}
357+
358+
if (*GlobalAdapter->ZeInitResult == ZE_RESULT_SUCCESS ||
359+
*GlobalAdapter->ZeInitDriversResult == ZE_RESULT_SUCCESS) {
360+
GlobalAdapter->ZeResult = ZE_RESULT_SUCCESS;
361+
} else {
362+
GlobalAdapter->ZeResult = ZE_RESULT_ERROR_UNINITIALIZED;
363+
}
252364
}
253365
assert(GlobalAdapter->ZeResult !=
254366
std::nullopt); // verify that level-zero is initialized
@@ -260,19 +372,11 @@ ur_adapter_handle_t_::ur_adapter_handle_t_()
260372
return;
261373
}
262374
if (*GlobalAdapter->ZeResult != ZE_RESULT_SUCCESS) {
263-
logger::error("zeInit: Level Zero initialization failure\n");
375+
logger::error("Level Zero initialization failure\n");
264376
result = ze2urResult(*GlobalAdapter->ZeResult);
265377

266378
return;
267379
}
268-
// Dynamically load the new L0 SysMan separate init and new EXP apis
269-
// separately. This must be done to avoid attempting to use symbols that do
270-
// not exist in older loader runtimes.
271-
#ifdef _WIN32
272-
HMODULE processHandle = GetModuleHandle(NULL);
273-
#else
274-
HMODULE processHandle = nullptr;
275-
#endif
276380

277381
// Check if the user has enabled the default L0 SysMan initialization.
278382
const int UrSysmanZesinitEnable = [] {

source/adapters/level_zero/adapter.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <optional>
1818
#include <ur/ur.hpp>
1919
#include <ze_api.h>
20+
#include <ze_ddi.h>
2021
#include <zes_ddi.h>
2122

2223
using PlatformVec = std::vector<std::unique_ptr<ur_platform_handle_t_>>;
@@ -31,7 +32,14 @@ struct ur_adapter_handle_t_ {
3132
zes_pfnDriverGetDeviceByUuidExp_t getDeviceByUUIdFunctionPtr = nullptr;
3233
zes_pfnDriverGet_t getSysManDriversFunctionPtr = nullptr;
3334
zes_pfnInit_t sysManInitFunctionPtr = nullptr;
35+
ze_pfnInitDrivers_t initDriversFunctionPtr = nullptr;
36+
ze_init_driver_type_desc_t InitDriversDesc = {
37+
ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC, nullptr, 0};
38+
uint32_t ZeInitDriversCount = 0;
39+
bool InitDriversSupported = false;
3440

41+
std::optional<ze_result_t> ZeInitDriversResult;
42+
std::optional<ze_result_t> ZeInitResult;
3543
std::optional<ze_result_t> ZeResult;
3644
std::optional<ze_result_t> ZesResult;
3745
ZeCache<Result<PlatformVec>> PlatformCache;

0 commit comments

Comments
 (0)