Skip to content

Commit 1be7c09

Browse files
authored
Merge branch 'master' into query_tracing_state
2 parents 20d14b5 + e64ee71 commit 1be7c09

File tree

6 files changed

+312
-0
lines changed

6 files changed

+312
-0
lines changed

doc/loader_api.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,25 @@ This document does not cover APIs specific to individual layers (ie. tracing) or
99

1010
Exposed Loader APIs will be defined in header files located in this repository at `include/loader`, and installed to `<prefix>/include/level_zero/loader`
1111

12+
### zelGetLoaderVersion
13+
14+
This API is used to retrieve the version information of the loader itself. Unlike `zelLoaderGetVersions`, this API provides a simplified interface to get only the loader's version without needing to query all components.
15+
16+
- __*version__ Pointer to a `zel_component_version_t` structure that will be filled with the loader's version information. Must be a valid, non-null pointer.
17+
18+
This function:
19+
- Returns `ZE_RESULT_SUCCESS` on successful retrieval of the loader version
20+
- Returns `ZE_RESULT_ERROR_INVALID_NULL_POINTER` if `version` is `nullptr`
21+
- Returns `ZE_RESULT_ERROR_UNINITIALIZED` if the loader library cannot be found or loaded (only possible in static builds with misconfigured library paths)
22+
- Does not require `zeInit()` or `zeInitDrivers()` to be called prior to invocation
23+
- Works with both static and dynamic loader builds without initialization
24+
- Is thread-safe and can be called from multiple threads
25+
26+
The returned `zel_component_version_t` structure contains:
27+
- `component_name`: Set to `"loader"`
28+
- `spec_version`: The Level Zero API specification version (`ZE_API_VERSION_CURRENT`)
29+
- `component_lib_version`: The loader library version with `major`, `minor`, and `patch` fields
30+
1231
### zelLoaderGetVersions
1332

1433
This API is used to retreive the version information of the loader itself and of any layers that are enabled.
@@ -64,3 +83,4 @@ The function returns:
6483
- `ZE_RESULT_ERROR_INVALID_NULL_POINTER` if the `enabled` pointer is null
6584

6685
This is a read-only, thread-safe operation that can be called multiple times concurrently. The tracing layer state is global to the process and reflects the current reference count maintained by `zelEnableTracingLayer` and `zelDisableTracingLayer` - the layer is considered enabled when the reference count is greater than zero.
86+

include/loader/ze_loader.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,75 @@ extern "C" {
3434
} zel_component_version_t;
3535

3636

37+
/**
38+
* @brief Retrieves version information for all components of the Level Zero loader.
39+
*
40+
* This function returns the versions of all loader components. It requires that
41+
* the driver initialization routine has been called prior to use.
42+
*
43+
* Preconditions:
44+
* - `zeInitDrivers()` must be successfully invoked before calling this function.
45+
*
46+
* Usage:
47+
* - If `versions` is `NULL`, the function writes the number of available component
48+
* versions to `*num_elems` and returns.
49+
* - If `versions` is non-NULL, provide an array large enough to hold `*num_elems`
50+
* entries; the function fills the array with the versions of all loader components.
51+
*
52+
* @param[out] num_elems
53+
* Pointer to a size_t that receives the number of available component version entries.
54+
* When `versions` is non-NULL, on success it may be updated to reflect the number
55+
* of entries written.
56+
*
57+
* @param[out] versions
58+
* Pointer to an array of `zel_component_version_t` to be filled with version data.
59+
* If set to `NULL`, no version data is returned and only `*num_elems` is populated.
60+
*
61+
* @return ze_result_t
62+
* - `ZE_RESULT_SUCCESS` on successful retrieval.
63+
* - `ZE_RESULT_ERROR_UNINITIALIZED` if `zeInitDrivers()` was not called.
64+
* - `ZE_RESULT_ERROR_INVALID_NULL_POINTER` if required pointers are `NULL`.
65+
* - `ZE_RESULT_ERROR_INVALID_SIZE` if the provided array is too small.
66+
* - Other `ze_result_t` error codes as appropriate.
67+
*/
3768
ZE_APIEXPORT ze_result_t ZE_APICALL
3869
zelLoaderGetVersions(
3970
size_t *num_elems, //Pointer to num versions to get.
4071
zel_component_version_t *versions); //Pointer to array of versions. If set to NULL, num_elems is returned
4172

73+
74+
/**
75+
* @brief Retrieves the Level Zero loader's version information.
76+
*
77+
* Populates the provided zel_component_version_t structure with the loader's
78+
* version details (e.g., major, minor, patch), allowing applications to
79+
* query and validate the loader's compatibility at runtime.
80+
*
81+
* Does not require zeInit() or zeInitDrivers() to be called prior to invocation.
82+
* Works with both static and dynamic loader builds without initialization.
83+
*
84+
* Thread-safety: This function is safe to call from multiple threads.
85+
* The implementation does not modify global state other than filling the
86+
* supplied version structure.
87+
*
88+
* @param[out] version
89+
* Pointer to a zel_component_version_t structure that will be filled with
90+
* the loader's version information. Must be a valid, non-null pointer.
91+
*
92+
* @return
93+
* - ZE_RESULT_SUCCESS on successful retrieval of the loader version.
94+
* - ZE_RESULT_ERROR_INVALID_NULL_POINTER if version is nullptr.
95+
* - ZE_RESULT_ERROR_UNINITIALIZED if the loader library cannot be found or loaded
96+
* (only possible in static builds with misconfigured library paths).
97+
* - Other ze_result_t error codes on failure conditions as defined by the API.
98+
*
99+
* @note The caller owns the memory for the version structure and must ensure
100+
* it remains valid for the duration of the call.
101+
*/
102+
ZE_DLLEXPORT ze_result_t ZE_APICALL
103+
zelGetLoaderVersion(zel_component_version_t *version
104+
);
105+
42106
typedef enum _zel_handle_type_t {
43107
ZEL_HANDLE_DRIVER,
44108
ZEL_HANDLE_DEVICE,

source/lib/ze_lib.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,54 @@ zelLoaderGetVersions(
389389
#endif
390390
}
391391

392+
ze_result_t ZE_APICALL
393+
zelGetLoaderVersion(
394+
zel_component_version_t *version) //Pointer to version structure to be filled with loader version information
395+
{
396+
#ifdef L0_STATIC_LOADER_BUILD
397+
// zelLoaderGetVersion doesn't require initialization, so we can load the library temporarily if needed
398+
HMODULE loaderHandle = nullptr;
399+
bool temporaryLoad = false;
400+
401+
if(ze_lib::context && ze_lib::context->loader) {
402+
// Use existing loader
403+
loaderHandle = ze_lib::context->loader;
404+
} else {
405+
// Temporarily load the loader library to get version info
406+
std::string loaderLibraryPath;
407+
auto loaderLibraryPathEnv = getenv_string("ZEL_LIBRARY_PATH");
408+
if (!loaderLibraryPathEnv.empty()) {
409+
loaderLibraryPath = loaderLibraryPathEnv;
410+
}
411+
#ifdef _WIN32
412+
else {
413+
loaderLibraryPath = readLevelZeroLoaderLibraryPath();
414+
}
415+
#endif
416+
std::string loaderFullLibraryPath = create_library_path(MAKE_LIBRARY_NAME( "ze_loader", L0_LOADER_VERSION), loaderLibraryPath.c_str());
417+
loaderHandle = LOAD_DRIVER_LIBRARY(loaderFullLibraryPath.c_str());
418+
if (nullptr == loaderHandle) {
419+
return ZE_RESULT_ERROR_UNINITIALIZED;
420+
}
421+
temporaryLoad = true;
422+
}
423+
424+
typedef ze_result_t (ZE_APICALL *zelLoaderGetVersion_t)(zel_component_version_t *version);
425+
auto getVersion = reinterpret_cast<zelLoaderGetVersion_t>(
426+
GET_FUNCTION_PTR(loaderHandle, "zelLoaderGetVersion") );
427+
ze_result_t result = getVersion(version);
428+
429+
// Clean up temporary load
430+
if (temporaryLoad && loaderHandle) {
431+
FREE_DRIVER_LIBRARY(loaderHandle);
432+
}
433+
434+
return result;
435+
#else
436+
return zelLoaderGetVersion(version);
437+
#endif
438+
}
439+
392440

393441
ze_result_t ZE_APICALL
394442
zelLoaderTranslateHandle(

source/loader/ze_loader_api.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@ zelLoaderGetVersionsInternal(
9292
return ZE_RESULT_SUCCESS;
9393
}
9494

95+
ZE_DLLEXPORT ze_result_t ZE_APICALL
96+
zelLoaderGetVersion(zel_component_version_t *version)
97+
{
98+
if(version == nullptr)
99+
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
100+
string_copy_s(version->component_name, "loader", ZEL_COMPONENT_STRING_SIZE);
101+
version->spec_version = ZE_API_VERSION_CURRENT;
102+
version->component_lib_version.major = LOADER_VERSION_MAJOR;
103+
version->component_lib_version.minor = LOADER_VERSION_MINOR;
104+
version->component_lib_version.patch = LOADER_VERSION_PATCH;
105+
106+
return ZE_RESULT_SUCCESS;
107+
}
95108

96109
ZE_DLLEXPORT ze_result_t ZE_APICALL
97110
zelLoaderTranslateHandleInternal(

test/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,26 @@ endif()
115115

116116
add_test(NAME tests_api COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingzeGetLoaderVersionsAPIThenValidVersionIsReturned*)
117117
set_property(TEST tests_api PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
118+
119+
# LoaderVersionAPI Tests
120+
add_test(NAME tests_loader_version_after_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionAfterInitThenValidVersionIsReturned*)
121+
set_property(TEST tests_loader_version_after_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
122+
123+
add_test(NAME tests_loader_version_null_pointer COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionWithNullPointerThenErrorIsReturned*)
124+
set_property(TEST tests_loader_version_null_pointer PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
125+
126+
add_test(NAME tests_loader_version_without_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionWithoutInitThenCorrectResultIsReturned*)
127+
set_property(TEST tests_loader_version_without_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
128+
129+
add_test(NAME tests_loader_version_before_and_after_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionBeforeAndAfterInitThenCorrectResultIsReturned*)
130+
set_property(TEST tests_loader_version_before_and_after_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
131+
132+
add_test(NAME tests_loader_version_multiple_times COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionMultipleTimesThenConsistentVersionIsReturned*)
133+
set_property(TEST tests_loader_version_multiple_times PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
134+
135+
add_test(NAME tests_loader_version_compare_apis COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenComparingzelGetLoaderVersionWithzelLoaderGetVersionsThenVersionsMatch*)
136+
set_property(TEST tests_loader_version_compare_apis PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
137+
118138
add_test(NAME tests_init_gpu_all COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithGPUTypeThenExpectPassWithGPUorAllOnly*)
119139
set_property(TEST tests_init_gpu_all PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
120140
add_test(NAME tests_init_npu_all COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithNPUTypeThenExpectPassWithNPUorAllOnly*)
@@ -793,6 +813,8 @@ set_property(TEST test_ze_and_zer_tracing_dynamic PROPERTY ENVIRONMENT "ZE_ENABL
793813
add_test(NAME test_zer_unsupported_and_ze_tracing_dynamic COMMAND tests --gtest_filter=*TracingParameterizedTest*GivenLoaderWithDynamicTracingEnabledAndZerApisUnsupportedAndBothZeAndZerCallbacksRegisteredWhenCallingBothApisThenTracingWorksForZeAndZerCallbacksAreStillInvoked*)
794814
set_property(TEST test_zer_unsupported_and_ze_tracing_dynamic PROPERTY ENVIRONMENT "ZE_ENABLE_NULL_DRIVER=1")
795815

816+
817+
796818
# ZER API Validation Layer Tests
797819
add_test(NAME test_zer_validation_layer_positive_case COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWithLoaderInterceptEnabledAndDdiExtSupportedWhenCallingRuntimeApisAfterZeInitDriversThenExpectNullDriverIsReachedSuccessfully)
798820
set_property(TEST test_zer_validation_layer_positive_case PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;ZE_ENABLE_VALIDATION_LAYER=1;ZE_ENABLE_PARAMETER_VALIDATION=1;ZE_ENABLE_HANDLE_LIFETIME=0;ZEL_ENABLE_EVENTS_CHECKER=1;ZEL_ENABLE_BASIC_LEAK_CHECKER=1;ZEL_ENABLE_CERTIFICATION_CHECKER=1")

test/loader_api.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,151 @@ TEST(
9292
}
9393
}
9494

95+
TEST(
96+
LoaderVersionAPI,
97+
GivenLoaderWhenCallingzelGetLoaderVersionAfterInitThenValidVersionIsReturned) {
98+
99+
uint32_t pCount = 0;
100+
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
101+
desc.flags = UINT32_MAX;
102+
desc.pNext = nullptr;
103+
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));
104+
105+
zel_component_version_t version = {};
106+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version));
107+
108+
// Verify component name is "loader"
109+
EXPECT_STREQ(version.component_name, "loader");
110+
111+
// Verify spec version is valid (current API version)
112+
EXPECT_GT(version.spec_version, 0);
113+
114+
// Verify library version components are valid
115+
EXPECT_GE(version.component_lib_version.major, 0);
116+
EXPECT_GE(version.component_lib_version.minor, 0);
117+
EXPECT_GE(version.component_lib_version.patch, 0);
118+
}
119+
120+
TEST(
121+
LoaderVersionAPI,
122+
GivenLoaderWhenCallingzelGetLoaderVersionWithNullPointerThenErrorIsReturned) {
123+
124+
uint32_t pCount = 0;
125+
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
126+
desc.flags = UINT32_MAX;
127+
desc.pNext = nullptr;
128+
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));
129+
130+
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_NULL_POINTER, zelGetLoaderVersion(nullptr));
131+
}
132+
133+
TEST(
134+
LoaderVersionAPI,
135+
GivenLoaderWhenCallingzelGetLoaderVersionWithoutInitThenCorrectResultIsReturned) {
136+
137+
zel_component_version_t version = {};
138+
139+
// Both static and dynamic builds: works without initialization
140+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version));
141+
142+
EXPECT_STREQ(version.component_name, "loader");
143+
EXPECT_GT(version.spec_version, 0);
144+
EXPECT_GE(version.component_lib_version.major, 0);
145+
EXPECT_GE(version.component_lib_version.minor, 0);
146+
EXPECT_GE(version.component_lib_version.patch, 0);
147+
}
148+
149+
TEST(
150+
LoaderVersionAPI,
151+
GivenLoaderWhenCallingzelGetLoaderVersionBeforeAndAfterInitThenCorrectResultIsReturned) {
152+
153+
// Get version before initialization
154+
zel_component_version_t version_before = {};
155+
156+
// Both static and dynamic builds: should work before init
157+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version_before));
158+
159+
// Initialize drivers
160+
uint32_t pCount = 0;
161+
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
162+
desc.flags = UINT32_MAX;
163+
desc.pNext = nullptr;
164+
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));
165+
166+
// Get version after initialization
167+
zel_component_version_t version_after = {};
168+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version_after));
169+
170+
// Verify both versions match
171+
EXPECT_STREQ(version_before.component_name, version_after.component_name);
172+
EXPECT_EQ(version_before.spec_version, version_after.spec_version);
173+
EXPECT_EQ(version_before.component_lib_version.major, version_after.component_lib_version.major);
174+
EXPECT_EQ(version_before.component_lib_version.minor, version_after.component_lib_version.minor);
175+
EXPECT_EQ(version_before.component_lib_version.patch, version_after.component_lib_version.patch);
176+
}
177+
178+
TEST(
179+
LoaderVersionAPI,
180+
GivenLoaderWhenCallingzelGetLoaderVersionMultipleTimesThenConsistentVersionIsReturned) {
181+
182+
uint32_t pCount = 0;
183+
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
184+
desc.flags = UINT32_MAX;
185+
desc.pNext = nullptr;
186+
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));
187+
188+
zel_component_version_t version1 = {};
189+
zel_component_version_t version2 = {};
190+
191+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version1));
192+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version2));
193+
194+
// Verify both calls return the same version
195+
EXPECT_STREQ(version1.component_name, version2.component_name);
196+
EXPECT_EQ(version1.spec_version, version2.spec_version);
197+
EXPECT_EQ(version1.component_lib_version.major, version2.component_lib_version.major);
198+
EXPECT_EQ(version1.component_lib_version.minor, version2.component_lib_version.minor);
199+
EXPECT_EQ(version1.component_lib_version.patch, version2.component_lib_version.patch);
200+
}
201+
202+
TEST(
203+
LoaderVersionAPI,
204+
GivenLoaderWhenComparingzelGetLoaderVersionWithzelLoaderGetVersionsThenVersionsMatch) {
205+
206+
uint32_t pCount = 0;
207+
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
208+
desc.flags = UINT32_MAX;
209+
desc.pNext = nullptr;
210+
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));
211+
212+
// Get version via zelGetLoaderVersion
213+
zel_component_version_t single_version = {};
214+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&single_version));
215+
216+
// Get versions via zelLoaderGetVersions
217+
size_t size = 0;
218+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelLoaderGetVersions(&size, nullptr));
219+
EXPECT_GT(size, 0);
220+
221+
std::vector<zel_component_version_t> versions(size);
222+
EXPECT_EQ(ZE_RESULT_SUCCESS, zelLoaderGetVersions(&size, versions.data()));
223+
224+
// Find the loader component in the versions array
225+
bool found_loader = false;
226+
for (const auto &component : versions) {
227+
if (strcmp(component.component_name, "loader") == 0) {
228+
found_loader = true;
229+
// Verify both APIs return the same version info
230+
EXPECT_EQ(single_version.spec_version, component.spec_version);
231+
EXPECT_EQ(single_version.component_lib_version.major, component.component_lib_version.major);
232+
EXPECT_EQ(single_version.component_lib_version.minor, component.component_lib_version.minor);
233+
EXPECT_EQ(single_version.component_lib_version.patch, component.component_lib_version.patch);
234+
break;
235+
}
236+
}
237+
EXPECT_TRUE(found_loader) << "Loader component not found in zelLoaderGetVersions output";
238+
}
239+
95240
TEST(
96241
LoaderInit,
97242
GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithTypesUnsupportedWithFailureThenSupportedTypesThenSuccessReturned) {

0 commit comments

Comments
 (0)