Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions include/loader/ze_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,75 @@ extern "C" {
} zel_component_version_t;


/**
* @brief Retrieves version information for all components of the Level Zero loader.
*
* This function returns the versions of all loader components. It requires that
* the driver initialization routine has been called prior to use.
*
* Preconditions:
* - `zeInitDrivers()` must be successfully invoked before calling this function.
*
* Usage:
* - If `versions` is `NULL`, the function writes the number of available component
* versions to `*num_elems` and returns.
* - If `versions` is non-NULL, provide an array large enough to hold `*num_elems`
* entries; the function fills the array with the versions of all loader components.
*
* @param[out] num_elems
* Pointer to a size_t that receives the number of available component version entries.
* When `versions` is non-NULL, on success it may be updated to reflect the number
* of entries written.
*
* @param[out] versions
* Pointer to an array of `zel_component_version_t` to be filled with version data.
* If set to `NULL`, no version data is returned and only `*num_elems` is populated.
*
* @return ze_result_t
* - `ZE_RESULT_SUCCESS` on successful retrieval.
* - `ZE_RESULT_ERROR_UNINITIALIZED` if `zeInitDrivers()` was not called.
* - `ZE_RESULT_ERROR_INVALID_NULL_POINTER` if required pointers are `NULL`.
* - `ZE_RESULT_ERROR_INVALID_SIZE` if the provided array is too small.
* - Other `ze_result_t` error codes as appropriate.
*/
ZE_APIEXPORT ze_result_t ZE_APICALL
zelLoaderGetVersions(
size_t *num_elems, //Pointer to num versions to get.
zel_component_version_t *versions); //Pointer to array of versions. If set to NULL, num_elems is returned


/**
* @brief Retrieves the Level Zero loader's version information.
*
* Populates the provided zel_component_version_t structure with the loader's
* version details (e.g., major, minor, patch), allowing applications to
* query and validate the loader's compatibility at runtime.
*
* Does not require zeInitDrivers to be called prior to invocation unless the
* application is using a static build of the loader.
*
* Thread-safety: This function is typically safe to call from multiple threads.
* The implementation does not modify global state other than filling the
* supplied version structure.
*
* @param[out] 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.
*
* @return
* - ZE_RESULT_SUCCESS on successful retrieval of the loader version.
* - ZE_RESULT_ERROR_INVALID_NULL_POINTER if version is nullptr.
* - ZE_RESULT_ERROR_UNINITIALIZED if the loader is not properly initialized.
* NOTE: this error only occurs with a static loader build.
* - Other ze_result_t error codes on failure conditions as defined by the API.
*
* @note The caller owns the memory for the version structure and must ensure
* it remains valid for the duration of the call.
*/
ZE_DLLEXPORT ze_result_t ZE_APICALL
zelGetLoaderVersion(zel_component_version_t *version
);

typedef enum _zel_handle_type_t {
ZEL_HANDLE_DRIVER,
ZEL_HANDLE_DEVICE,
Expand Down
16 changes: 16 additions & 0 deletions source/lib/ze_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,22 @@ zelLoaderGetVersions(
#endif
}

ze_result_t ZE_APICALL
zelGetLoaderVersion(
zel_component_version_t *version) //Pointer to version structure to be filled with loader version information
{
#ifdef L0_STATIC_LOADER_BUILD
if(!ze_lib::context || nullptr == ze_lib::context->loader)
return ZE_RESULT_ERROR_UNINITIALIZED;
typedef ze_result_t (ZE_APICALL *zelLoaderGetVersion_t)(zel_component_version_t *version);
auto getVersion = reinterpret_cast<zelLoaderGetVersion_t>(
GET_FUNCTION_PTR(ze_lib::context->loader, "zelLoaderGetVersion") );
return getVersion(version);
#else
return zelLoaderGetVersion(version);
#endif
}


ze_result_t ZE_APICALL
zelLoaderTranslateHandle(
Expand Down
13 changes: 13 additions & 0 deletions source/loader/ze_loader_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ zelLoaderGetVersionsInternal(
return ZE_RESULT_SUCCESS;
}

ZE_DLLEXPORT ze_result_t ZE_APICALL
zelLoaderGetVersion(zel_component_version_t *version)
{
if(version == nullptr)
return ZE_RESULT_ERROR_INVALID_NULL_POINTER;
string_copy_s(version->component_name, "loader", ZEL_COMPONENT_STRING_SIZE);
version->spec_version = ZE_API_VERSION_CURRENT;
version->component_lib_version.major = LOADER_VERSION_MAJOR;
version->component_lib_version.minor = LOADER_VERSION_MINOR;
version->component_lib_version.patch = LOADER_VERSION_PATCH;

return ZE_RESULT_SUCCESS;
}

ZE_DLLEXPORT ze_result_t ZE_APICALL
zelLoaderTranslateHandleInternal(
Expand Down
22 changes: 22 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ endif()

add_test(NAME tests_api COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingzeGetLoaderVersionsAPIThenValidVersionIsReturned*)
set_property(TEST tests_api PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

# LoaderVersionAPI Tests
add_test(NAME tests_loader_version_after_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionAfterInitThenValidVersionIsReturned*)
set_property(TEST tests_loader_version_after_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_loader_version_null_pointer COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionWithNullPointerThenErrorIsReturned*)
set_property(TEST tests_loader_version_null_pointer PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_loader_version_without_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionWithoutInitThenCorrectResultIsReturned*)
set_property(TEST tests_loader_version_without_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_loader_version_before_and_after_init COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionBeforeAndAfterInitThenCorrectResultIsReturned*)
set_property(TEST tests_loader_version_before_and_after_init PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_loader_version_multiple_times COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenCallingzelGetLoaderVersionMultipleTimesThenConsistentVersionIsReturned*)
set_property(TEST tests_loader_version_multiple_times PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_loader_version_compare_apis COMMAND tests --gtest_filter=*LoaderVersionAPI*GivenLoaderWhenComparingzelGetLoaderVersionWithzelLoaderGetVersionsThenVersionsMatch*)
set_property(TEST tests_loader_version_compare_apis PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")

add_test(NAME tests_init_gpu_all COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithGPUTypeThenExpectPassWithGPUorAllOnly*)
set_property(TEST tests_init_gpu_all PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1")
add_test(NAME tests_init_npu_all COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithNPUTypeThenExpectPassWithNPUorAllOnly*)
Expand Down Expand Up @@ -755,6 +775,8 @@ set_property(TEST test_ze_and_zer_tracing_dynamic PROPERTY ENVIRONMENT "ZE_ENABL
add_test(NAME test_zer_unsupported_and_ze_tracing_dynamic COMMAND tests --gtest_filter=*TracingParameterizedTest*GivenLoaderWithDynamicTracingEnabledAndZerApisUnsupportedAndBothZeAndZerCallbacksRegisteredWhenCallingBothApisThenTracingWorksForZeAndZerCallbacksAreStillInvoked*)
set_property(TEST test_zer_unsupported_and_ze_tracing_dynamic PROPERTY ENVIRONMENT "ZE_ENABLE_NULL_DRIVER=1")



# ZER API Validation Layer Tests
add_test(NAME test_zer_validation_layer_positive_case COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWithLoaderInterceptEnabledAndDdiExtSupportedWhenCallingRuntimeApisAfterZeInitDriversThenExpectNullDriverIsReachedSuccessfully)
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")
Expand Down
157 changes: 157 additions & 0 deletions test/loader_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,163 @@ TEST(
}
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenCallingzelGetLoaderVersionAfterInitThenValidVersionIsReturned) {

uint32_t pCount = 0;
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
desc.flags = UINT32_MAX;
desc.pNext = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));

zel_component_version_t version = {};
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version));

// Verify component name is "loader"
EXPECT_STREQ(version.component_name, "loader");

// Verify spec version is valid (current API version)
EXPECT_GT(version.spec_version, 0);

// Verify library version components are valid
EXPECT_GE(version.component_lib_version.major, 0);
EXPECT_GE(version.component_lib_version.minor, 0);
EXPECT_GE(version.component_lib_version.patch, 0);
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenCallingzelGetLoaderVersionWithNullPointerThenErrorIsReturned) {

uint32_t pCount = 0;
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
desc.flags = UINT32_MAX;
desc.pNext = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));

EXPECT_EQ(ZE_RESULT_ERROR_INVALID_NULL_POINTER, zelGetLoaderVersion(nullptr));
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenCallingzelGetLoaderVersionWithoutInitThenCorrectResultIsReturned) {

zel_component_version_t version = {};

#ifdef L0_STATIC_LOADER_BUILD
// Static build: requires initialization
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zelGetLoaderVersion(&version));
#else
// Dynamic build: works without initialization
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version));

EXPECT_STREQ(version.component_name, "loader");
EXPECT_GT(version.spec_version, 0);
EXPECT_GE(version.component_lib_version.major, 0);
EXPECT_GE(version.component_lib_version.minor, 0);
EXPECT_GE(version.component_lib_version.patch, 0);
#endif
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenCallingzelGetLoaderVersionBeforeAndAfterInitThenCorrectResultIsReturned) {

// Get version before initialization
zel_component_version_t version_before = {};

#ifdef L0_STATIC_LOADER_BUILD
// Static build: should fail before init
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, zelGetLoaderVersion(&version_before));
#else
// Dynamic build: should work before init
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version_before));
#endif

// Initialize drivers
uint32_t pCount = 0;
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
desc.flags = UINT32_MAX;
desc.pNext = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));

// Get version after initialization
zel_component_version_t version_after = {};
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version_after));

#ifndef L0_STATIC_LOADER_BUILD
// Dynamic build: verify both versions match
EXPECT_STREQ(version_before.component_name, version_after.component_name);
EXPECT_EQ(version_before.spec_version, version_after.spec_version);
EXPECT_EQ(version_before.component_lib_version.major, version_after.component_lib_version.major);
EXPECT_EQ(version_before.component_lib_version.minor, version_after.component_lib_version.minor);
EXPECT_EQ(version_before.component_lib_version.patch, version_after.component_lib_version.patch);
#endif
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenCallingzelGetLoaderVersionMultipleTimesThenConsistentVersionIsReturned) {

uint32_t pCount = 0;
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
desc.flags = UINT32_MAX;
desc.pNext = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));

zel_component_version_t version1 = {};
zel_component_version_t version2 = {};

EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version1));
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&version2));

// Verify both calls return the same version
EXPECT_STREQ(version1.component_name, version2.component_name);
EXPECT_EQ(version1.spec_version, version2.spec_version);
EXPECT_EQ(version1.component_lib_version.major, version2.component_lib_version.major);
EXPECT_EQ(version1.component_lib_version.minor, version2.component_lib_version.minor);
EXPECT_EQ(version1.component_lib_version.patch, version2.component_lib_version.patch);
}

TEST(
LoaderVersionAPI,
GivenLoaderWhenComparingzelGetLoaderVersionWithzelLoaderGetVersionsThenVersionsMatch) {

uint32_t pCount = 0;
ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC};
desc.flags = UINT32_MAX;
desc.pNext = nullptr;
EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc));

// Get version via zelGetLoaderVersion
zel_component_version_t single_version = {};
EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetLoaderVersion(&single_version));

// Get versions via zelLoaderGetVersions
size_t size = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, zelLoaderGetVersions(&size, nullptr));
EXPECT_GT(size, 0);

std::vector<zel_component_version_t> versions(size);
EXPECT_EQ(ZE_RESULT_SUCCESS, zelLoaderGetVersions(&size, versions.data()));

// Find the loader component in the versions array
bool found_loader = false;
for (const auto &component : versions) {
if (strcmp(component.component_name, "loader") == 0) {
found_loader = true;
// Verify both APIs return the same version info
EXPECT_EQ(single_version.spec_version, component.spec_version);
EXPECT_EQ(single_version.component_lib_version.major, component.component_lib_version.major);
EXPECT_EQ(single_version.component_lib_version.minor, component.component_lib_version.minor);
EXPECT_EQ(single_version.component_lib_version.patch, component.component_lib_version.patch);
break;
}
}
EXPECT_TRUE(found_loader) << "Loader component not found in zelLoaderGetVersions output";
}

TEST(
LoaderInit,
GivenLevelZeroLoaderPresentWhenCallingZeInitDriversWithTypesUnsupportedWithFailureThenSupportedTypesThenSuccessReturned) {
Expand Down
Loading