diff --git a/level_zero/api/driver_experimental/public/zex_driver.cpp b/level_zero/api/driver_experimental/public/zex_driver.cpp index 17781139dd..6402e7d810 100644 --- a/level_zero/api/driver_experimental/public/zex_driver.cpp +++ b/level_zero/api/driver_experimental/public/zex_driver.cpp @@ -63,6 +63,15 @@ zeIntelGetDriverVersionString( return ZE_RESULT_SUCCESS; } +ze_context_handle_t ZE_APICALL zeDriverGetDefaultContext( + ze_driver_handle_t hDriver) { + return L0::DriverHandle::fromHandle(hDriver)->getDefaultContext(); +} + +ze_context_handle_t ZE_APICALL zerDriverGetDefaultContext() { + return L0::DriverHandle::fromHandle(L0::globalDriverHandles->front())->getDefaultContext(); +} + extern "C" { ZE_APIEXPORT ze_result_t ZE_APICALL diff --git a/level_zero/core/source/driver/driver_handle.h b/level_zero/core/source/driver/driver_handle.h index d79618bc9b..f4c9a0562a 100644 --- a/level_zero/core/source/driver/driver_handle.h +++ b/level_zero/core/source/driver/driver_handle.h @@ -85,6 +85,8 @@ struct DriverHandle : BaseDriver, NEO::NonCopyableAndNonMovableClass { virtual ze_result_t getErrorDescription(const char **ppString) = 0; virtual ze_result_t clearErrorDescription() = 0; + virtual ze_context_handle_t getDefaultContext() const = 0; + static DriverHandle *fromHandle(ze_driver_handle_t handle) { return static_cast(handle); } inline ze_driver_handle_t toHandle() { return this; } diff --git a/level_zero/core/source/driver/driver_handle_imp.cpp b/level_zero/core/source/driver/driver_handle_imp.cpp index 6ab1621118..dec9e08643 100644 --- a/level_zero/core/source/driver/driver_handle_imp.cpp +++ b/level_zero/core/source/driver/driver_handle_imp.cpp @@ -34,6 +34,7 @@ #include "level_zero/core/source/driver/host_pointer_manager.h" #include "level_zero/core/source/fabric/fabric.h" #include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h" +#include "level_zero/core/source/helpers/default_descriptors.h" #include "level_zero/core/source/image/image.h" #include "level_zero/core/source/semaphore/external_semaphore_imp.h" #include "level_zero/driver_experimental/zex_common.h" @@ -213,6 +214,10 @@ ze_result_t DriverHandleImp::getExtensionProperties(uint32_t *pCount, } DriverHandleImp::~DriverHandleImp() { + if (this->defaultContext) { + L0::Context::fromHandle(this->defaultContext)->destroy(); + this->defaultContext = nullptr; + } if (this->externalSemaphoreController) { this->externalSemaphoreController.reset(); } @@ -323,6 +328,8 @@ ze_result_t DriverHandleImp::initialize(std::vector } } + createContext(&DefaultDescriptors::contextDesc, 0u, nullptr, &defaultContext); + return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/source/driver/driver_handle_imp.h b/level_zero/core/source/driver/driver_handle_imp.h index 4636a4a1dd..44cf823d79 100644 --- a/level_zero/core/source/driver/driver_handle_imp.h +++ b/level_zero/core/source/driver/driver_handle_imp.h @@ -147,6 +147,7 @@ struct DriverHandleImp : public DriverHandle { NEO::MemoryManager *memoryManager = nullptr; NEO::SVMAllocsManager *svmAllocsManager = nullptr; NEO::UsmMemAllocPool usmHostMemAllocPool; + ze_context_handle_t defaultContext = nullptr; std::unique_ptr rtasLibraryHandle; bool rtasLibraryUnavailable = false; @@ -177,6 +178,10 @@ struct DriverHandleImp : public DriverHandle { ze_result_t getErrorDescription(const char **ppString) override; ze_result_t clearErrorDescription() override; + ze_context_handle_t getDefaultContext() const override { + return defaultContext; + } + protected: NEO::GraphicsAllocation *getPeerAllocation(Device *device, NEO::SVMAllocsManager::MapBasedAllocationTracker &storage, diff --git a/level_zero/core/source/driver/extension_function_address.cpp b/level_zero/core/source/driver/extension_function_address.cpp index fe40725f13..7bfd24b52b 100644 --- a/level_zero/core/source/driver/extension_function_address.cpp +++ b/level_zero/core/source/driver/extension_function_address.cpp @@ -29,6 +29,8 @@ void *ExtensionFunctionAddressHelper::getExtensionFunctionAddress(const std::str RETURN_FUNC_PTR_IF_EXIST(zexDriverImportExternalPointer); RETURN_FUNC_PTR_IF_EXIST(zexDriverReleaseImportedPointer); RETURN_FUNC_PTR_IF_EXIST(zexDriverGetHostPointerBaseAddress); + RETURN_FUNC_PTR_IF_EXIST(zeDriverGetDefaultContext); + RETURN_FUNC_PTR_IF_EXIST(zerDriverGetDefaultContext); RETURN_FUNC_PTR_IF_EXIST(zexKernelGetBaseAddress); RETURN_FUNC_PTR_IF_EXIST(zexKernelGetArgumentSize); diff --git a/level_zero/core/source/helpers/default_descriptors.cpp b/level_zero/core/source/helpers/default_descriptors.cpp index 1197e4145e..460b978c01 100644 --- a/level_zero/core/source/helpers/default_descriptors.cpp +++ b/level_zero/core/source/helpers/default_descriptors.cpp @@ -12,6 +12,12 @@ namespace L0 { namespace DefaultDescriptors { +const ze_context_desc_t contextDesc{ + .stype = ze_structure_type_t::ZE_STRUCTURE_TYPE_CONTEXT_DESC, + .pNext = nullptr, + .flags = static_cast(0), +}; + static const zex_intel_queue_copy_operations_offload_hint_exp_desc_t copyOffloadHint = { .stype = ZEX_INTEL_STRUCTURE_TYPE_QUEUE_COPY_OPERATIONS_OFFLOAD_HINT_EXP_PROPERTIES, .pNext = nullptr, diff --git a/level_zero/core/source/helpers/default_descriptors.h b/level_zero/core/source/helpers/default_descriptors.h index 80cd14281b..a08d69989b 100644 --- a/level_zero/core/source/helpers/default_descriptors.h +++ b/level_zero/core/source/helpers/default_descriptors.h @@ -12,6 +12,7 @@ namespace L0 { namespace DefaultDescriptors { +extern const ze_context_desc_t contextDesc; extern const ze_command_queue_desc_t commandQueueDesc; extern const ze_device_mem_alloc_desc_t deviceMemDesc; extern const ze_host_mem_alloc_desc_t hostMemDesc; diff --git a/level_zero/core/test/unit_tests/mocks/mock_context.h b/level_zero/core/test/unit_tests/mocks/mock_context.h index f1b50a25f7..a40b1c4317 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_context.h +++ b/level_zero/core/test/unit_tests/mocks/mock_context.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,6 +20,12 @@ struct WhiteBox<::L0::Context> : public ::L0::Context {}; using Context = WhiteBox<::L0::Context>; +template <> +struct WhiteBox<::L0::ContextImp> : public ::L0::ContextImp { + using ::L0::ContextImp::devices; + using ::L0::ContextImp::numDevices; +}; + template <> struct Mock : public Context { Mock() = default; diff --git a/level_zero/core/test/unit_tests/sources/driver/test_driver.cpp b/level_zero/core/test/unit_tests/sources/driver/test_driver.cpp index 818ae2ff6a..ee276e8cfa 100644 --- a/level_zero/core/test/unit_tests/sources/driver/test_driver.cpp +++ b/level_zero/core/test/unit_tests/sources/driver/test_driver.cpp @@ -37,6 +37,7 @@ #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" #include "level_zero/core/test/unit_tests/fixtures/host_pointer_manager_fixture.h" #include "level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h" +#include "level_zero/core/test/unit_tests/mocks/mock_context.h" #include "level_zero/core/test/unit_tests/mocks/mock_driver.h" #include "level_zero/core/test/unit_tests/mocks/mock_driver_handle.h" #include "level_zero/driver_experimental/zex_api.h" @@ -690,6 +691,58 @@ TEST(DriverTest, givenProgramDebuggingEnvVarValue2WhenCreatingDriverThenEnablePr delete driverHandle; } +TEST(DriverTest, whenCreatingDriverThenDefaultContextWithAllDevicesIsCreated) { + + ze_result_t returnValue; + NEO::HardwareInfo hwInfo = *NEO::defaultHwInfo.get(); + + NEO::MockDevice *neoDevice = NEO::MockDevice::createWithNewExecutionEnvironment(&hwInfo); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + + L0EnvVariables envVariables = {}; + + auto driverHandle = whiteboxCast(static_cast<::L0::DriverHandleImp *>(DriverHandle::create(std::move(devices), envVariables, &returnValue))); + EXPECT_NE(nullptr, driverHandle); + + auto defaultContext = driverHandle->getDefaultContext(); + ASSERT_NE(nullptr, defaultContext); + + auto context = static_cast *>(defaultContext); + + EXPECT_NE(0u, context->numDevices); + EXPECT_EQ(context->numDevices, context->devices.size()); + EXPECT_EQ(context->devices.size(), driverHandle->devices.size()); + for (auto i = 0u; i < context->numDevices; i++) { + EXPECT_EQ(context->devices[i], driverHandle->devices[i]); + } + + delete driverHandle; +} + +TEST(DriverTest, givenDriverWhenGetDefaultContextApiIsCalledThenProperHandleIsReturned) { + + ze_result_t returnValue; + NEO::HardwareInfo hwInfo = *NEO::defaultHwInfo.get(); + + NEO::MockDevice *neoDevice = NEO::MockDevice::createWithNewExecutionEnvironment(&hwInfo); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + + L0EnvVariables envVariables = {}; + + auto driverHandle = whiteboxCast(static_cast<::L0::DriverHandleImp *>(DriverHandle::create(std::move(devices), envVariables, &returnValue))); + EXPECT_NE(nullptr, driverHandle); + + auto defaultContext = zeDriverGetDefaultContext(driverHandle); + + EXPECT_NE(nullptr, defaultContext); + + EXPECT_EQ(defaultContext, driverHandle->getDefaultContext()); + + delete driverHandle; +} + TEST(DriverTest, givenBuiltinsAsyncInitEnabledWhenCreatingDriverThenMakeSureBuiltinsInitIsCompletedOnExitOfDriverHandleInitialization) { VariableBackup backup(&ultHwConfig); ultHwConfig.useinitBuiltinsAsyncEnabled = true; @@ -861,6 +914,14 @@ TEST_F(DriverHandleTest, EXPECT_NE(nullptr, driverHandle); } +TEST_F(DriverHandleTest, + givenInitializedDriverWhenZerDriverGetDefaultContextIsCalledThenDefaultContextFromFirstDriverHandleIsReturned) { + globalDriverHandles->push_back(nullptr); + auto defaultContext = zerDriverGetDefaultContext(); + + EXPECT_EQ(defaultContext, driverHandle->getDefaultContext()); +} + TEST_F(DriverHandleTest, givenInitializedDriverWhenZeDriverGetIsCalledWithGreaterThanZeroCountAndNullDriverHandleThenInvalidNullPointerIsReturned) { uint32_t count = 0; @@ -1118,6 +1179,8 @@ TEST_F(DriverExperimentalApiTest, whenRetrievingApiFunctionThenExpectProperPoint decltype(&zexDriverImportExternalPointer) expectedImport = L0::zexDriverImportExternalPointer; decltype(&zexDriverReleaseImportedPointer) expectedRelease = L0::zexDriverReleaseImportedPointer; decltype(&zexDriverGetHostPointerBaseAddress) expectedGet = L0::zexDriverGetHostPointerBaseAddress; + decltype(&zeDriverGetDefaultContext) expectedZeDriverGetDefaultContext = zeDriverGetDefaultContext; + decltype(&zerDriverGetDefaultContext) expectedZerDriverGetDefaultContext = zerDriverGetDefaultContext; decltype(&zexKernelGetBaseAddress) expectedKernelGetBaseAddress = L0::zexKernelGetBaseAddress; decltype(&zeIntelGetDriverVersionString) expectedIntelGetDriverVersionString = zeIntelGetDriverVersionString; decltype(&zeIntelMediaCommunicationCreate) expectedIntelMediaCommunicationCreate = L0::zeIntelMediaCommunicationCreate; @@ -1141,6 +1204,12 @@ TEST_F(DriverExperimentalApiTest, whenRetrievingApiFunctionThenExpectProperPoint EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGetExtensionFunctionAddress(driverHandle, "zexDriverGetHostPointerBaseAddress", &funPtr)); EXPECT_EQ(expectedGet, reinterpret_cast(funPtr)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGetExtensionFunctionAddress(driverHandle, "zeDriverGetDefaultContext", &funPtr)); + EXPECT_EQ(expectedZeDriverGetDefaultContext, reinterpret_cast(funPtr)); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGetExtensionFunctionAddress(driverHandle, "zerDriverGetDefaultContext", &funPtr)); + EXPECT_EQ(expectedZerDriverGetDefaultContext, reinterpret_cast(funPtr)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeDriverGetExtensionFunctionAddress(driverHandle, "zexKernelGetBaseAddress", &funPtr)); EXPECT_EQ(expectedKernelGetBaseAddress, reinterpret_cast(funPtr)); diff --git a/level_zero/include/level_zero/ze_intel_gpu.h b/level_zero/include/level_zero/ze_intel_gpu.h index 5dae243d0d..97d1a3fdae 100644 --- a/level_zero/include/level_zero/ze_intel_gpu.h +++ b/level_zero/include/level_zero/ze_intel_gpu.h @@ -275,6 +275,26 @@ zeIntelKernelGetBinaryExp( char *pKernelBinary ///< [in,out] pointer to storage area for GEN ISA binary function ); +/// @brief Get default context associated with driver +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// - Default context contains all devices within driver instance +/// @returns +/// - Context handle associated with driver +ze_context_handle_t zeDriverGetDefaultContext(ze_driver_handle_t hDriver); ///> [in] handle of the driver + +/// @brief Get default context associated with default driver +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// - Default context contains all devices within default driver instance +/// @returns +/// - Context handle associated with default driver +ze_context_handle_t zerDriverGetDefaultContext(); + #if defined(__cplusplus) } // extern "C" #endif