Skip to content

Commit 44fba79

Browse files
authored
Refactor Init to delay Library Load (#379)
* Refactor Init to delay Library Load - Delay to load of the L0 Driver Libraries until the user has directly requested the library to be loaded thru the flags. - Remove the "pretest" of driver support and instead assume driver support based on naming and registry categorization. Speeds up loader init. - Moved init of drivers until zInitDrivers or zeInit - Added ULTs to verify the new init_driver functionality Signed-off-by: Neil R. Spruit <[email protected]>
1 parent 45560f7 commit 44fba79

37 files changed

+4014
-1900
lines changed

.github/workflows/build-quick-static-n-1.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ jobs:
5454
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
5555
-D CMAKE_BUILD_TYPE=Release \
5656
-D BUILD_STATIC=0 \
57+
-D BUILD_L0_LOADER_TESTS=1 \
5758
..
5859
make -j$(nproc)
5960

.github/workflows/build-quick-static.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
-D CMAKE_C_COMPILER_LAUNCHER=ccache \
3636
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
3737
-D CMAKE_BUILD_TYPE=Release \
38+
-D BUILD_L0_LOADER_TESTS=1 \
3839
-D BUILD_STATIC=0 \
3940
..
4041
make -j$(nproc)

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# Level zero loader changelog
2+
## v1.26.0
3+
* Refactor L0 Init to delay loading of driver libraries until flags match the drivers requested.
24
## v1.25.2
35
* Enable support for Dynamic Tracing of zer* APIs
46
* Fix issues with zer* apis during validation layer intercepts

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ if(MSVC AND (MSVC_VERSION LESS 1900))
1313
endif()
1414

1515
# This project follows semantic versioning (https://semver.org/)
16-
project(level-zero VERSION 1.25.2)
16+
project(level-zero VERSION 1.26.0)
1717
include(GNUInstallDirs)
1818

1919
find_package(Git)

PRODUCT_GUID.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1.25.2
2-
738dfd00-2750-4425-9d91-6b68a2590ded
1+
1.26.0
2+
af2b4113-ecb0-4777-b3ce-d81307ed1156

samples/zello_world/zello_world.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int main( int argc, char *argv[] )
4242
bool tracing_runtime_enabled = false;
4343
bool legacy_init = false;
4444
bool tracing_enabled = false;
45+
bool npu_test = false;
4546
if( argparse( argc, argv, "-null", "--enable_null_driver" ) )
4647
{
4748
putenv_safe( const_cast<char *>( "ZE_ENABLE_NULL_DRIVER=1" ) );
@@ -69,13 +70,25 @@ int main( int argc, char *argv[] )
6970
{
7071
legacy_init = true;
7172
}
73+
if( argparse( argc, argv, "-npu", "--enable_npu" ) )
74+
{
75+
npu_test = true;
76+
}
7277

7378
ze_result_t status;
74-
const ze_device_type_t type = ZE_DEVICE_TYPE_GPU;
79+
ze_device_type_t type = ZE_DEVICE_TYPE_GPU;
80+
if (npu_test) {
81+
std::cout << "NPU Test Enabled. Looking for NPU devices." << std::endl;
82+
type = ZE_DEVICE_TYPE_VPU;
83+
}
7584

7685
ze_init_driver_type_desc_t driverTypeDesc = {};
7786
driverTypeDesc.stype = ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC;
78-
driverTypeDesc.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU;
87+
if (npu_test) {
88+
driverTypeDesc.flags = ZE_INIT_DRIVER_TYPE_FLAG_NPU;
89+
} else {
90+
driverTypeDesc.flags = ZE_INIT_DRIVER_TYPE_FLAG_GPU;
91+
}
7992
driverTypeDesc.pNext = nullptr;
8093

8194
ze_driver_handle_t pDriver = nullptr;

scripts/templates/ldrddi.cpp.mako

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ using namespace loader_driver_ddi;
2222

2323
namespace loader
2424
{
25+
__${x}dlllocal ze_result_t ${X}_APICALL
26+
${n}loaderInitDriverDDITables(loader::driver_t *driver) {
27+
ze_result_t result = ZE_RESULT_SUCCESS;
28+
%for tbl in th.get_pfntables(specs, meta, n, tags):
29+
result = ${tbl['export']['name']}FromDriver(driver);
30+
if (result != ZE_RESULT_SUCCESS) {
31+
return result;
32+
}
33+
%endfor
34+
return result;
35+
}
2536
%for obj in th.extract_objs(specs, r"function"):
2637
<%
2738
ret_type = obj['return_type']
@@ -65,6 +76,12 @@ namespace loader
6576
if(drv.initStatus != ZE_RESULT_SUCCESS)
6677
continue;
6778
%endif
79+
if (!drv.handle || !drv.ddiInitialized) {
80+
auto res = loader::context->init_driver( drv, flags, nullptr );
81+
if (res != ZE_RESULT_SUCCESS) {
82+
continue;
83+
}
84+
}
6885
%if re.match(r"Init", obj['name']) and namespace == "zes":
6986
if (!drv.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}) {
7087
drv.initSysManStatus = ZE_RESULT_ERROR_UNINITIALIZED;
@@ -90,6 +107,13 @@ namespace loader
90107

91108
%elif re.match(r"\w+DriverGet$", th.make_func_name(n, tags, obj)) or re.match(r"\w+InitDrivers$", th.make_func_name(n, tags, obj)):
92109
uint32_t total_driver_handle_count = 0;
110+
%if re.match(r"\w+InitDrivers$", th.make_func_name(n, tags, obj)):
111+
for( auto& drv : loader::context->zeDrivers ) {
112+
if (!drv.handle || !drv.ddiInitialized) {
113+
loader::context->init_driver( drv, 0, desc);
114+
}
115+
}
116+
%endif
93117

94118
{
95119
std::lock_guard<std::mutex> lock(loader::context->sortMutex);
@@ -122,15 +146,16 @@ namespace loader
122146
%endif
123147
{
124148
%if not (re.match(r"\w+InitDrivers$", th.make_func_name(n, tags, obj))) and namespace != "zes":
125-
if(drv.initStatus != ZE_RESULT_SUCCESS)
149+
if(drv.initStatus != ZE_RESULT_SUCCESS || !drv.ddiInitialized)
126150
continue;
127151
%elif namespace == "zes":
128-
if(drv.initStatus != ZE_RESULT_SUCCESS || drv.initSysManStatus != ZE_RESULT_SUCCESS)
152+
if(drv.initStatus != ZE_RESULT_SUCCESS || drv.initSysManStatus != ZE_RESULT_SUCCESS || !drv.ddiInitialized)
129153
continue;
130154
%else:
131155
if (!drv.dditable.${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)}) {
132156
%if re.match(r"\w+InitDrivers$", th.make_func_name(n, tags, obj)):
133157
drv.initDriversStatus = ${X}_RESULT_ERROR_UNINITIALIZED;
158+
result = ${X}_RESULT_ERROR_UNINITIALIZED;
134159
%else:
135160
drv.initStatus = ${X}_RESULT_ERROR_UNINITIALIZED;
136161
%endif
@@ -179,7 +204,8 @@ namespace loader
179204
for( uint32_t i = 0; i < library_driver_handle_count; ++i ) {
180205
uint32_t driver_index = total_driver_handle_count + i;
181206
%if namespace != "zes":
182-
drv.zerDriverHandle = phDrivers[ driver_index ];
207+
if (drv.zerddiInitResult == ZE_RESULT_SUCCESS)
208+
drv.zerDriverHandle = phDrivers[ driver_index ];
183209
if (drv.driverDDIHandleSupportQueried == false) {
184210
uint32_t extensionCount = 0;
185211
ze_result_t res = drv.dditable.ze.Driver.pfnGetExtensionProperties(phDrivers[ driver_index ], &extensionCount, nullptr);
@@ -503,6 +529,52 @@ ${tbl['export']['name']}Legacy()
503529

504530
%endfor
505531

532+
%for tbl in th.get_pfntables(specs, meta, n, tags):
533+
///////////////////////////////////////////////////////////////////////////////
534+
/// @brief Exported function for filling application's ${tbl['name']} table
535+
/// with current process' addresses
536+
///
537+
/// @returns
538+
/// - ::${X}_RESULT_SUCCESS
539+
/// - ::${X}_RESULT_ERROR_UNINITIALIZED
540+
/// - ::${X}_RESULT_ERROR_INVALID_NULL_POINTER
541+
/// - ::${X}_RESULT_ERROR_UNSUPPORTED_VERSION
542+
__${x}dlllocal ${x}_result_t ${X}_APICALL
543+
${tbl['export']['name']}FromDriver(loader::driver_t *driver)
544+
{
545+
${x}_result_t result = ${X}_RESULT_SUCCESS;
546+
if(driver->initStatus != ZE_RESULT_SUCCESS)
547+
return driver->initStatus;
548+
auto getTable = reinterpret_cast<${tbl['pfn']}>(
549+
GET_FUNCTION_PTR( driver->handle, "${tbl['export']['name']}") );
550+
if(!getTable)
551+
%if th.isNewProcTable(tbl['export']['name']) is True and namespace != "zer":
552+
{
553+
//It is valid to not have this proc addr table
554+
return ${X}_RESULT_SUCCESS;
555+
}
556+
%else:
557+
return driver->initStatus;
558+
%endif
559+
%if tbl['experimental'] is False and namespace != "zer": #//Experimental Tables may not be implemented in driver
560+
auto getTableResult = getTable( loader::context->ddi_init_version, &driver->dditable.${n}.${tbl['name']});
561+
if(getTableResult == ZE_RESULT_SUCCESS) {
562+
loader::context->configured_version = loader::context->ddi_init_version;
563+
} else
564+
driver->initStatus = getTableResult;
565+
%if namespace != "zes":
566+
%if tbl['name'] == "Global" and namespace != "zer":
567+
if (driver->dditable.ze.Global.pfnInitDrivers) {
568+
loader::context->initDriversSupport = true;
569+
}
570+
%endif
571+
%endif
572+
%else:
573+
result = getTable( loader::context->ddi_init_version, &driver->dditable.${n}.${tbl['name']});
574+
%endif
575+
return result;
576+
}
577+
%endfor
506578
%for tbl in th.get_pfntables(specs, meta, n, tags):
507579
///////////////////////////////////////////////////////////////////////////////
508580
/// @brief Exported function for filling application's ${tbl['name']} table
@@ -534,63 +606,26 @@ ${tbl['export']['name']}(
534606
if( loader::context->version < version )
535607
return ${X}_RESULT_ERROR_UNSUPPORTED_VERSION;
536608

609+
loader::context->ddi_init_version = version;
610+
537611
${x}_result_t result = ${X}_RESULT_SUCCESS;
538612

539-
%if tbl['experimental'] is False and namespace != "zer": #//Experimental Tables may not be implemented in driver
540-
bool atLeastOneDriverValid = false;
541-
%endif
542-
// Load the device-driver DDI tables
543613
%if namespace != "zes":
544-
for( auto& drv : loader::context->zeDrivers )
614+
auto driverCount = loader::context->zeDrivers.size();
615+
auto firstDriver = &loader::context->zeDrivers[0];
545616
%else:
546-
for( auto& drv : *loader::context->sysmanInstanceDrivers )
617+
auto driverCount = loader::context->sysmanInstanceDrivers->size();
618+
auto firstDriver = &loader::context->sysmanInstanceDrivers->at(0);
547619
%endif
548-
{
549-
if(drv.initStatus != ZE_RESULT_SUCCESS)
550-
continue;
551-
auto getTable = reinterpret_cast<${tbl['pfn']}>(
552-
GET_FUNCTION_PTR( drv.handle, "${tbl['export']['name']}") );
553-
if(!getTable)
554-
%if th.isNewProcTable(tbl['export']['name']) is True and namespace != "zer":
555-
{
556-
atLeastOneDriverValid = true;
557-
//It is valid to not have this proc addr table
558-
continue;
559-
}
560-
%else:
561-
continue;
562-
%endif
563-
%if tbl['experimental'] is False and namespace != "zer": #//Experimental Tables may not be implemented in driver
564-
auto getTableResult = getTable( version, &drv.dditable.${n}.${tbl['name']});
565-
if(getTableResult == ZE_RESULT_SUCCESS) {
566-
atLeastOneDriverValid = true;
567-
loader::context->configured_version = version;
568-
} else
569-
drv.initStatus = getTableResult;
570-
%if namespace != "zes":
571-
%if tbl['name'] == "Global" and namespace != "zer":
572-
if (drv.dditable.ze.Global.pfnInitDrivers) {
573-
loader::context->initDriversSupport = true;
574-
}
575-
%endif
576-
%endif
577-
%else:
578-
result = getTable( version, &drv.dditable.${n}.${tbl['name']});
579-
%endif
620+
if (driverCount == 1 && firstDriver && !loader::context->forceIntercept) {
621+
result = ${tbl['export']['name']}FromDriver(firstDriver);
580622
}
581623

582-
%if tbl['experimental'] is False and namespace != "zer": #//Experimental Tables may not be implemented in driver
583-
if(!atLeastOneDriverValid)
584-
result = ${X}_RESULT_ERROR_UNINITIALIZED;
585-
else
586-
result = ${X}_RESULT_SUCCESS;
587-
%endif
588-
589624
if( ${X}_RESULT_SUCCESS == result )
590625
{
591626
%if namespace != "zes":
592627
if( ( loader::context->zeDrivers.size() > 1 ) || loader::context->forceIntercept )
593-
%else:
628+
%elif namespace == "zes":
594629
if( ( loader::context->sysmanInstanceDrivers->size() > 1 ) || loader::context->forceIntercept )
595630
%endif
596631
{

scripts/templates/ldrddi.h.mako

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ from templates import helper as th
2020

2121
namespace loader
2222
{
23+
///////////////////////////////////////////////////////////////////////////////
24+
// Forward declaration for driver_t so this header can reference loader::driver_t*
25+
// without requiring inclusion of ze_loader_internal.h (which includes this file).
26+
struct driver_t;
2327
///////////////////////////////////////////////////////////////////////////////
2428
%for obj in th.extract_objs(specs, r"handle"):
2529
%if 'class' in obj:
@@ -32,6 +36,8 @@ namespace loader
3236

3337
%endif
3438
%endfor
39+
__${x}dlllocal ze_result_t ${X}_APICALL
40+
${n}loaderInitDriverDDITables(loader::driver_t *driver);
3541
}
3642

3743
namespace loader_driver_ddi
@@ -57,6 +63,8 @@ extern "C" {
5763
%for tbl in th.get_pfntables(specs, meta, n, tags):
5864
__${x}dlllocal void ${X}_APICALL
5965
${tbl['export']['name']}Legacy();
66+
__${x}dlllocal ze_result_t ${X}_APICALL
67+
${tbl['export']['name']}FromDriver(loader::driver_t *driver);
6068
%endfor
6169

6270
#if defined(__cplusplus)

scripts/templates/ldrddi_driver_ddi.cpp.mako

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,15 @@ namespace loader_driver_ddi
103103
// Check if the default driver supports DDI Handles
104104
if (loader::context->defaultZerDriverHandle == nullptr) {
105105
%if ret_type == 'ze_result_t':
106+
if (loader::context->zeDrivers.front().zerddiInitResult == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) {
107+
return ${X}_RESULT_ERROR_UNSUPPORTED_FEATURE;
108+
}
106109
return ${X}_RESULT_ERROR_UNINITIALIZED;
107110
%else:
111+
if (loader::context->zeDrivers.front().zerddiInitResult == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) {
112+
error_state::setErrorDesc("ERROR UNSUPPORTED FEATURE");
113+
return ${failure_return};
114+
}
108115
error_state::setErrorDesc("ERROR UNINITIALIZED");
109116
return ${failure_return};
110117
%endif

scripts/templates/nullddi.cpp.mako

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,23 @@ namespace driver
5454
// generic implementation
5555
%if re.match("Init", obj['name']):
5656
%if re.match("InitDrivers", obj['name']):
57+
// Check compile-time definitions first
58+
bool is_npu = false;
59+
bool is_gpu = false;
60+
#ifdef ZEL_NULL_DRIVER_TYPE_NPU
61+
is_npu = true;
62+
#endif
63+
64+
#ifdef ZEL_NULL_DRIVER_TYPE_GPU
65+
is_gpu = true;
66+
#endif
5767
auto driver_type = getenv_string( "ZEL_TEST_NULL_DRIVER_TYPE" );
58-
if (std::strcmp(driver_type.c_str(), "GPU") == 0) {
68+
if (std::strcmp(driver_type.c_str(), "GPU") == 0 || is_gpu) {
5969
if (!(desc->flags & ZE_INIT_DRIVER_TYPE_FLAG_GPU)) {
6070
return ${X}_RESULT_ERROR_UNINITIALIZED;
6171
}
6272
}
63-
if (std::strcmp(driver_type.c_str(), "NPU") == 0) {
73+
if (std::strcmp(driver_type.c_str(), "NPU") == 0 || is_npu) {
6474
if (!(desc->flags & ZE_INIT_DRIVER_TYPE_FLAG_NPU)) {
6575
return ${X}_RESULT_ERROR_UNINITIALIZED;
6676
}

0 commit comments

Comments
 (0)