From 284541484591a83d4861e57784bc3f6391737c3e Mon Sep 17 00:00:00 2001 From: Lukasz Jobczyk Date: Mon, 30 Jan 2023 13:41:26 +0000 Subject: [PATCH] Reuse builtin module and init selected builtin on device init -start async thread at device initialization which initializes selected builtins and exits -share module across builtins using same binary Resolves: NEO-7644 Signed-off-by: Lukasz Jobczyk --- .../source/builtin/builtin_functions_lib.h | 5 +- .../builtin/builtin_functions_lib_impl.cpp | 69 ++++++++++++------- .../builtin/builtin_functions_lib_impl.h | 28 +++++--- .../dll/create_builtin_functions_lib.cpp | 6 +- .../core/source/driver/driver_handle_imp.cpp | 4 ++ .../mocks/mock_builtin_functions_lib_impl.h | 15 ++-- ...ck_builtin_functions_lib_impl_timestamps.h | 22 +++--- .../sources/builtin/built_in_spv_tests_l0.cpp | 1 - .../builtin/builtin_functions_tests.cpp | 60 +++++++++++++--- .../create_ult_builtin_functions_lib.cpp | 5 ++ .../sources/cmdlist/test_cmdlist_5.cpp | 20 +++--- .../tools/test/unit_tests/CMakeLists.txt | 4 +- .../test/common/base_ult_config_listener.cpp | 2 +- shared/test/common/helpers/ult_hw_config.h | 1 + 14 files changed, 162 insertions(+), 80 deletions(-) diff --git a/level_zero/core/source/builtin/builtin_functions_lib.h b/level_zero/core/source/builtin/builtin_functions_lib.h index f50135c0d9..2c7dbd6ba9 100644 --- a/level_zero/core/source/builtin/builtin_functions_lib.h +++ b/level_zero/core/source/builtin/builtin_functions_lib.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -65,8 +65,9 @@ struct BuiltinFunctionsLib { virtual Kernel *getFunction(Builtin func) = 0; virtual Kernel *getImageFunction(ImageBuiltin func) = 0; - virtual void initBuiltinKernel(Builtin builtId) = 0; + virtual void initBuiltinKernel(Builtin builtId, bool asyncInit) = 0; virtual void initBuiltinImageKernel(ImageBuiltin func) = 0; + virtual void ensureInitCompletion() = 0; [[nodiscard]] MOCKABLE_VIRTUAL std::unique_lock obtainUniqueOwnership(); protected: diff --git a/level_zero/core/source/builtin/builtin_functions_lib_impl.cpp b/level_zero/core/source/builtin/builtin_functions_lib_impl.cpp index 18935761ce..38e7b4731b 100644 --- a/level_zero/core/source/builtin/builtin_functions_lib_impl.cpp +++ b/level_zero/core/source/builtin/builtin_functions_lib_impl.cpp @@ -12,7 +12,6 @@ #include "level_zero/core/source/device/device.h" #include "level_zero/core/source/kernel/kernel.h" -#include "level_zero/core/source/module/module.h" namespace NEO { const char *getAdditionalBuiltinAsString(EBuiltInOps::Type builtin) { @@ -24,18 +23,14 @@ namespace L0 { BuiltinFunctionsLibImpl::BuiltinData::~BuiltinData() { func.reset(); - module.reset(); } BuiltinFunctionsLibImpl::BuiltinData::BuiltinData() = default; -BuiltinFunctionsLibImpl::BuiltinData::BuiltinData(std::unique_ptr &&mod, std::unique_ptr &&ker) { - module = std::move(mod); - func = std::move(ker); -} +BuiltinFunctionsLibImpl::BuiltinData::BuiltinData(Module *module, std::unique_ptr &&ker) : module(module), func(std::move(ker)) {} std::unique_lock BuiltinFunctionsLib::obtainUniqueOwnership() { return std::unique_lock(this->ownershipMutex); } -void BuiltinFunctionsLibImpl::initBuiltinKernel(Builtin func) { +void BuiltinFunctionsLibImpl::initBuiltinKernel(Builtin func, bool asyncInit) { const char *builtinName = nullptr; NEO::EBuiltInOps::Type builtin; @@ -125,7 +120,7 @@ void BuiltinFunctionsLibImpl::initBuiltinKernel(Builtin func) { }; auto builtId = static_cast(func); - builtins[builtId] = loadBuiltIn(builtin, builtinName); + builtins[builtId] = loadBuiltIn(builtin, builtinName, asyncInit); } void BuiltinFunctionsLibImpl::initBuiltinImageKernel(ImageBuiltin func) { @@ -182,14 +177,22 @@ void BuiltinFunctionsLibImpl::initBuiltinImageKernel(ImageBuiltin func) { }; auto builtId = static_cast(func); - imageBuiltins[builtId] = loadBuiltIn(builtin, builtinName); + imageBuiltins[builtId] = loadBuiltIn(builtin, builtinName, false); +} + +BuiltinFunctionsLibImpl::BuiltinFunctionsLibImpl(Device *device, NEO::BuiltIns *builtInsLib) : device(device), builtInsLib(builtInsLib) { + if (initBuiltinsAsyncEnabled()) { + this->initAsyncComplete = false; + this->initAsync = std::async(std::launch::async, &BuiltinFunctionsLibImpl::initBuiltinKernel, this, Builtin::FillBufferImmediate, true); + } } Kernel *BuiltinFunctionsLibImpl::getFunction(Builtin func) { auto builtId = static_cast(func); + this->ensureInitCompletion(); if (builtins[builtId].get() == nullptr) { - initBuiltinKernel(func); + initBuiltinKernel(func, false); } return builtins[builtId]->func.get(); @@ -198,6 +201,7 @@ Kernel *BuiltinFunctionsLibImpl::getFunction(Builtin func) { Kernel *BuiltinFunctionsLibImpl::getImageFunction(ImageBuiltin func) { auto builtId = static_cast(func); + this->ensureInitCompletion(); if (imageBuiltins[builtId].get() == nullptr) { initBuiltinImageKernel(func); } @@ -205,7 +209,7 @@ Kernel *BuiltinFunctionsLibImpl::getImageFunction(ImageBuiltin func) { return imageBuiltins[builtId]->func.get(); } -std::unique_ptr BuiltinFunctionsLibImpl::loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName) { +std::unique_ptr BuiltinFunctionsLibImpl::loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName, bool asyncInit) { using BuiltInCodeType = NEO::BuiltinCode::ECodeType; StackVec supportedTypes{}; @@ -223,27 +227,46 @@ std::unique_ptr BuiltinFunctionsLibImpl::l } } - [[maybe_unused]] ze_result_t res; - std::unique_ptr module; - ze_module_handle_t moduleHandle; - ze_module_desc_t moduleDesc = {}; - moduleDesc.format = builtinCode.type == BuiltInCodeType::Binary ? ZE_MODULE_FORMAT_NATIVE : ZE_MODULE_FORMAT_IL_SPIRV; - moduleDesc.pInputModule = reinterpret_cast(&builtinCode.resource[0]); - moduleDesc.inputSize = builtinCode.resource.size(); - res = device->createModule(&moduleDesc, &moduleHandle, nullptr, ModuleType::Builtin); - UNRECOVERABLE_IF(res != ZE_RESULT_SUCCESS); + if (builtinCode.type != BuiltInCodeType::Binary && asyncInit) { + return nullptr; + } - module.reset(Module::fromHandle(moduleHandle)); + [[maybe_unused]] ze_result_t res; + + if (this->modules.size() <= builtin) { + this->modules.resize(builtin + 1u); + } + + if (this->modules[builtin].get() == nullptr) { + std::unique_ptr module; + ze_module_handle_t moduleHandle; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = builtinCode.type == BuiltInCodeType::Binary ? ZE_MODULE_FORMAT_NATIVE : ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = reinterpret_cast(&builtinCode.resource[0]); + moduleDesc.inputSize = builtinCode.resource.size(); + res = device->createModule(&moduleDesc, &moduleHandle, nullptr, ModuleType::Builtin); + UNRECOVERABLE_IF(res != ZE_RESULT_SUCCESS); + + module.reset(Module::fromHandle(moduleHandle)); + this->modules[builtin] = std::move(module); + } std::unique_ptr kernel; ze_kernel_handle_t kernelHandle; ze_kernel_desc_t kernelDesc = {}; kernelDesc.pKernelName = builtInName; - res = module->createKernel(&kernelDesc, &kernelHandle); + res = this->modules[builtin]->createKernel(&kernelDesc, &kernelHandle); DEBUG_BREAK_IF(res != ZE_RESULT_SUCCESS); kernel.reset(Kernel::fromHandle(kernelHandle)); - return std::unique_ptr(new BuiltinData{std::move(module), std::move(kernel)}); + return std::unique_ptr(new BuiltinData{modules[builtin].get(), std::move(kernel)}); +} + +void BuiltinFunctionsLibImpl::ensureInitCompletion() { + if (!this->initAsyncComplete) { + this->initAsync.wait(); + this->initAsyncComplete = true; + } } } // namespace L0 diff --git a/level_zero/core/source/builtin/builtin_functions_lib_impl.h b/level_zero/core/source/builtin/builtin_functions_lib_impl.h index 3378cf6117..7fcc8fe937 100644 --- a/level_zero/core/source/builtin/builtin_functions_lib_impl.h +++ b/level_zero/core/source/builtin/builtin_functions_lib_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,7 +7,13 @@ #pragma once +#include "shared/source/os_interface/os_thread.h" + #include "level_zero/core/source/builtin/builtin_functions_lib.h" +#include "level_zero/core/source/module/module.h" + +#include +#include namespace NEO { namespace EBuiltInOps { @@ -17,15 +23,12 @@ class BuiltIns; } // namespace NEO namespace L0 { -struct Module; struct Kernel; struct Device; struct BuiltinFunctionsLibImpl : BuiltinFunctionsLib { struct BuiltinData; - BuiltinFunctionsLibImpl(Device *device, NEO::BuiltIns *builtInsLib) - : device(device), builtInsLib(builtInsLib) { - } + BuiltinFunctionsLibImpl(Device *device, NEO::BuiltIns *builtInsLib); ~BuiltinFunctionsLibImpl() override { builtins->reset(); imageBuiltins->reset(); @@ -33,22 +36,29 @@ struct BuiltinFunctionsLibImpl : BuiltinFunctionsLib { Kernel *getFunction(Builtin func) override; Kernel *getImageFunction(ImageBuiltin func) override; - void initBuiltinKernel(Builtin builtId) override; + void initBuiltinKernel(Builtin builtId, bool asyncInit) override; void initBuiltinImageKernel(ImageBuiltin func) override; - MOCKABLE_VIRTUAL std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName); + void ensureInitCompletion() override; + MOCKABLE_VIRTUAL std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName, bool asyncInit); + + static bool initBuiltinsAsyncEnabled(); protected: + std::vector> modules = {}; std::unique_ptr builtins[static_cast(Builtin::COUNT)]; std::unique_ptr imageBuiltins[static_cast(ImageBuiltin::COUNT)]; Device *device; NEO::BuiltIns *builtInsLib; + + std::future initAsync = {}; + bool initAsyncComplete = true; }; struct BuiltinFunctionsLibImpl::BuiltinData { MOCKABLE_VIRTUAL ~BuiltinData(); BuiltinData(); - BuiltinData(std::unique_ptr &&mod, std::unique_ptr &&ker); + BuiltinData(Module *module, std::unique_ptr &&ker); - std::unique_ptr module; + Module *module = nullptr; std::unique_ptr func; }; } // namespace L0 diff --git a/level_zero/core/source/dll/create_builtin_functions_lib.cpp b/level_zero/core/source/dll/create_builtin_functions_lib.cpp index 7d66b45774..05b21bd5c0 100644 --- a/level_zero/core/source/dll/create_builtin_functions_lib.cpp +++ b/level_zero/core/source/dll/create_builtin_functions_lib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -16,4 +16,8 @@ std::unique_ptr BuiltinFunctionsLib::create(Device *device, return std::unique_ptr(new BuiltinFunctionsLibImpl(device, builtins)); } +bool BuiltinFunctionsLibImpl::initBuiltinsAsyncEnabled() { + return true; +} + } // namespace L0 diff --git a/level_zero/core/source/driver/driver_handle_imp.cpp b/level_zero/core/source/driver/driver_handle_imp.cpp index bd1030d59c..0a729323a0 100644 --- a/level_zero/core/source/driver/driver_handle_imp.cpp +++ b/level_zero/core/source/driver/driver_handle_imp.cpp @@ -18,6 +18,7 @@ #include "shared/source/memory_manager/unified_memory_manager.h" #include "shared/source/os_interface/os_library.h" +#include "level_zero/core/source/builtin/builtin_functions_lib.h" #include "level_zero/core/source/context/context_imp.h" #include "level_zero/core/source/device/device_imp.h" #include "level_zero/core/source/driver/driver_imp.h" @@ -161,6 +162,9 @@ DriverHandleImp::~DriverHandleImp() { } for (auto &device : this->devices) { + if (device->getBuiltinFunctionsLib()) { + device->getBuiltinFunctionsLib()->ensureInitCompletion(); + } delete device; } diff --git a/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h b/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h index 047616f839..a683b84920 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h +++ b/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -23,23 +23,25 @@ struct MockBuiltinFunctionsLibImpl : BuiltinFunctionsLibImpl { dummyKernel = std::unique_ptr>(new Mock<::L0::Kernel>()); dummyModule = std::unique_ptr(new Mock(device, nullptr)); dummyKernel->module = dummyModule.get(); + mockModule = std::unique_ptr(new Mock(device, nullptr)); } - void initBuiltinKernel(L0::Builtin func) override { + void initBuiltinKernel(L0::Builtin func, bool asyncInit) override { auto builtId = static_cast(func); if (builtins[builtId].get() == nullptr) { - builtins[builtId] = loadBuiltIn(NEO::EBuiltInOps::CopyBufferToBuffer, "copyBufferToBufferBytesSingle"); + builtins[builtId] = loadBuiltIn(NEO::EBuiltInOps::CopyBufferToBuffer, "copyBufferToBufferBytesSingle", false); } } void initBuiltinImageKernel(L0::ImageBuiltin func) override { auto builtId = static_cast(func); if (imageBuiltins[builtId].get() == nullptr) { - imageBuiltins[builtId] = loadBuiltIn(NEO::EBuiltInOps::CopyImage3dToBuffer, "CopyImage3dToBuffer16Bytes"); + imageBuiltins[builtId] = loadBuiltIn(NEO::EBuiltInOps::CopyImage3dToBuffer, "CopyImage3dToBuffer16Bytes", false); } } std::unique_ptr> dummyKernel; std::unique_ptr dummyModule; + std::unique_ptr mockModule; Kernel *getFunction(Builtin func) override { return dummyKernel.get(); @@ -49,11 +51,10 @@ struct MockBuiltinFunctionsLibImpl : BuiltinFunctionsLibImpl { return dummyKernel.get(); } - std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName) override { + std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName, bool asyncInit) override { std::unique_ptr mockKernel(new Mock<::L0::Kernel>()); - std::unique_ptr mockModule(new Mock(device, nullptr)); - return std::unique_ptr(new BuiltinData{std::move(mockModule), std::move(mockKernel)}); + return std::unique_ptr(new BuiltinData{mockModule.get(), std::move(mockKernel)}); } }; } // namespace ult diff --git a/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl_timestamps.h b/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl_timestamps.h index 12f0fd72d8..961f8f9862 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl_timestamps.h +++ b/level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl_timestamps.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -17,25 +17,21 @@ namespace ult { struct MockBuiltinDataTimestamp : BuiltinFunctionsLibImpl::BuiltinData { using BuiltinFunctionsLibImpl::BuiltinData::BuiltinData; - - ~MockBuiltinDataTimestamp() override { - module.release(); - } }; struct MockBuiltinFunctionsLibImplTimestamps : BuiltinFunctionsLibImpl { using BuiltinFunctionsLibImpl::BuiltinFunctionsLibImpl; - void initBuiltinKernel(Builtin func) override { + void initBuiltinKernel(Builtin func, bool asyncInit) override { switch (static_cast(func)) { case Builtin::QueryKernelTimestamps: if (builtins[0].get() == nullptr) { - builtins[0] = loadBuiltIn(NEO::EBuiltInOps::QueryKernelTimestamps, "QueryKernelTimestamps"); + builtins[0] = loadBuiltIn(NEO::EBuiltInOps::QueryKernelTimestamps, "QueryKernelTimestamps", false); } break; case Builtin::QueryKernelTimestampsWithOffsets: if (builtins[1].get() == nullptr) { - builtins[1] = loadBuiltIn(NEO::EBuiltInOps::QueryKernelTimestamps, "QueryKernelTimestampsWithOffsets"); + builtins[1] = loadBuiltIn(NEO::EBuiltInOps::QueryKernelTimestamps, "QueryKernelTimestampsWithOffsets", false); } break; default: @@ -50,14 +46,15 @@ struct MockBuiltinFunctionsLibImplTimestamps : BuiltinFunctionsLibImpl { return func == Builtin::QueryKernelTimestampsWithOffsets ? builtins[1]->func.get() : builtins[0]->func.get(); } - std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName) override { + std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName, bool asyncInit) override { using BuiltInCodeType = NEO::BuiltinCode::ECodeType; auto builtInCodeType = NEO::DebugManager.flags.RebuildPrecompiledKernels.get() ? BuiltInCodeType::Intermediate : BuiltInCodeType::Binary; auto builtInCode = builtInsLib->getBuiltinsLib().getBuiltinCode(builtin, builtInCodeType, *device->getNEODevice()); [[maybe_unused]] ze_result_t res; - std::unique_ptr module; + + Module *module; ze_module_handle_t moduleHandle; ze_module_desc_t moduleDesc = {}; moduleDesc.format = builtInCode.type == BuiltInCodeType::Binary ? ZE_MODULE_FORMAT_NATIVE : ZE_MODULE_FORMAT_IL_SPIRV; @@ -65,8 +62,7 @@ struct MockBuiltinFunctionsLibImplTimestamps : BuiltinFunctionsLibImpl { moduleDesc.inputSize = builtInCode.resource.size(); res = device->createModule(&moduleDesc, &moduleHandle, nullptr, ModuleType::Builtin); UNRECOVERABLE_IF(res != ZE_RESULT_SUCCESS); - - module.reset(Module::fromHandle(moduleHandle)); + module = Module::fromHandle(moduleHandle); std::unique_ptr kernel; ze_kernel_handle_t kernelHandle; @@ -76,7 +72,7 @@ struct MockBuiltinFunctionsLibImplTimestamps : BuiltinFunctionsLibImpl { DEBUG_BREAK_IF(res != ZE_RESULT_SUCCESS); kernel.reset(Kernel::fromHandle(kernelHandle)); - return std::unique_ptr(new MockBuiltinDataTimestamp{std::move(module), std::move(kernel)}); + return std::unique_ptr(new MockBuiltinDataTimestamp{module, std::move(kernel)}); } }; diff --git a/level_zero/core/test/unit_tests/sources/builtin/built_in_spv_tests_l0.cpp b/level_zero/core/test/unit_tests/sources/builtin/built_in_spv_tests_l0.cpp index 1419947a1e..4c923b6045 100644 --- a/level_zero/core/test/unit_tests/sources/builtin/built_in_spv_tests_l0.cpp +++ b/level_zero/core/test/unit_tests/sources/builtin/built_in_spv_tests_l0.cpp @@ -43,7 +43,6 @@ HWTEST_F(BuiltInTestL0, givenDeviceWithUnregisteredBinaryBuiltinWhenGettingBuilt pDevice->getRootDeviceEnvironment().getMutableHardwareInfo()->platform.usRevId += 0xdead; L0::BuiltinFunctionsLibImpl builtinFunctionsLib{&deviceL0, pDevice->getBuiltIns()}; for (uint32_t builtId = 0; builtId < static_cast(L0::Builtin::COUNT); builtId++) { - deviceL0.formatForModule = {}; ASSERT_NE(nullptr, builtinFunctionsLib.getFunction(static_cast(builtId))); EXPECT_EQ(ZE_MODULE_FORMAT_NATIVE, deviceL0.formatForModule); } diff --git a/level_zero/core/test/unit_tests/sources/builtin/builtin_functions_tests.cpp b/level_zero/core/test/unit_tests/sources/builtin/builtin_functions_tests.cpp index b41c09641e..39a75184ea 100644 --- a/level_zero/core/test/unit_tests/sources/builtin/builtin_functions_tests.cpp +++ b/level_zero/core/test/unit_tests/sources/builtin/builtin_functions_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -8,6 +8,8 @@ #include "shared/source/built_ins/built_ins.h" #include "shared/source/execution_environment/root_device_environment.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/memory_management.h" +#include "shared/test/common/helpers/ult_hw_config.h" #include "shared/test/common/mocks/mock_compiler_interface_spirv.h" #include "shared/test/common/test_macros/hw_test.h" @@ -26,21 +28,27 @@ class BuiltinFunctionsLibFixture : public DeviceFixture { public: struct MockBuiltinFunctionsLibImpl : BuiltinFunctionsLibImpl { using BuiltinFunctionsLibImpl::builtins; + using BuiltinFunctionsLibImpl::ensureInitCompletion; using BuiltinFunctionsLibImpl::getFunction; using BuiltinFunctionsLibImpl::imageBuiltins; - MockBuiltinFunctionsLibImpl(L0::Device *device, NEO::BuiltIns *builtInsLib) : BuiltinFunctionsLibImpl(device, builtInsLib) {} - std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName) override { - std::unique_ptr mockKernel(new Mock<::L0::Kernel>()); - std::unique_ptr mockModule(new Mock(device, nullptr)); - - return std::unique_ptr(new BuiltinData{std::move(mockModule), std::move(mockKernel)}); + using BuiltinFunctionsLibImpl::initAsyncComplete; + MockBuiltinFunctionsLibImpl(L0::Device *device, NEO::BuiltIns *builtInsLib) : BuiltinFunctionsLibImpl(device, builtInsLib) { + mockModule = std::unique_ptr(new Mock(device, nullptr)); } + std::unique_ptr loadBuiltIn(NEO::EBuiltInOps::Type builtin, const char *builtInName, bool asyncInit) override { + std::unique_ptr mockKernel(new Mock<::L0::Kernel>()); + + return std::unique_ptr(new BuiltinData{mockModule.get(), std::move(mockKernel)}); + } + std::unique_ptr mockModule; }; void setUp() { DeviceFixture::setUp(); mockDevicePtr = std::unique_ptr>(new MockDeviceForSpv(device->getNEODevice(), device->getNEODevice()->getExecutionEnvironment(), driverHandle.get())); mockBuiltinFunctionsLibImpl.reset(new MockBuiltinFunctionsLibImpl(mockDevicePtr.get(), neoDevice->getBuiltIns())); + mockBuiltinFunctionsLibImpl->ensureInitCompletion(); + EXPECT_TRUE(mockBuiltinFunctionsLibImpl->initAsyncComplete); } void tearDown() { mockBuiltinFunctionsLibImpl.reset(); @@ -105,7 +113,37 @@ HWTEST_F(TestBuiltinFunctionsLibImpl, givenCallToBuiltinFunctionWithWrongIdThenE EXPECT_EQ(nullptr, mockBuiltinFunctionsLibImpl->builtins[builtId]); } uint32_t builtId = static_cast(Builtin::COUNT) + 1; - EXPECT_THROW(mockBuiltinFunctionsLibImpl->initBuiltinKernel(static_cast(builtId)), std::exception); + EXPECT_THROW(mockBuiltinFunctionsLibImpl->initBuiltinKernel(static_cast(builtId), false), std::exception); +} + +HWTEST_F(TestBuiltinFunctionsLibImpl, whenCreateBuiltinFunctionsLibThenImmediateFillIsLoaded) { + struct MockBuiltinFunctionsLibImpl : public BuiltinFunctionsLibImpl { + using BuiltinFunctionsLibImpl::BuiltinFunctionsLibImpl; + using BuiltinFunctionsLibImpl::builtins; + using BuiltinFunctionsLibImpl::ensureInitCompletion; + using BuiltinFunctionsLibImpl::initAsyncComplete; + }; + + EXPECT_TRUE(mockBuiltinFunctionsLibImpl->initAsyncComplete); + VariableBackup backup(&ultHwConfig); + ultHwConfig.useinitBuiltinsAsyncEnabled = true; + MockBuiltinFunctionsLibImpl lib(device, device->getNEODevice()->getBuiltIns()); + EXPECT_FALSE(lib.initAsyncComplete); + lib.ensureInitCompletion(); + EXPECT_TRUE(lib.initAsyncComplete); + for (uint32_t builtId = 0; builtId < static_cast(Builtin::COUNT); builtId++) { + if (builtId == static_cast(Builtin::FillBufferImmediate)) { + EXPECT_NE(nullptr, lib.builtins[builtId]); + } else { + EXPECT_EQ(nullptr, lib.builtins[builtId]); + } + } + uint32_t builtId = static_cast(Builtin::COUNT) + 1; + EXPECT_THROW(lib.initBuiltinKernel(static_cast(builtId), false), std::exception); + + /* std::async may create a detached thread - completion of the scheduled task can be ensured, + but there is no way to ensure that actual OS thread exited and its resources are freed */ + MemoryManagement::fastLeaksDetectionMode = MemoryManagement::LeakDetectionMode::TURN_OFF_LEAK_DETECTION; } HWTEST_F(TestBuiltinFunctionsLibImpl, givenCompilerInterfaceWhenCreateDeviceAndImageSupportedThenBuiltinsImageFunctionsAreLoaded) { @@ -166,7 +204,7 @@ HWTEST_F(TestBuiltinFunctionsLibImpl, givenRebuildPrecompiledKernelsDebugFlagWhe MockDeviceForRebuildBuilins testDevice(device); testDevice.builtins.reset(new BuiltinFunctionsLibImpl(&testDevice, neoDevice->getBuiltIns())); for (uint32_t builtId = 0; builtId < static_cast(Builtin::COUNT); builtId++) { - testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId)); + testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId), false); } EXPECT_TRUE(testDevice.createModuleCalled); @@ -199,7 +237,7 @@ HWTEST_F(TestBuiltinFunctionsLibImpl, givenNotToRebuildPrecompiledKernelsDebugFl L0::Device *testDevicePtr = &testDevice; testDevice.builtins.reset(new BuiltinFunctionsLibImpl(testDevicePtr, neoDevice->getBuiltIns())); for (uint32_t builtId = 0; builtId < static_cast(Builtin::COUNT); builtId++) { - testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId)); + testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId), false); } EXPECT_TRUE(testDevice.createModuleCalled); @@ -229,7 +267,7 @@ HWTEST_F(TestBuiltinFunctionsLibImpl, GivenBuiltinsWhenInitializingFunctionsThen L0::Device *testDevicePtr = &testDevice; testDevice.builtins.reset(new BuiltinFunctionsLibImpl(testDevicePtr, neoDevice->getBuiltIns())); for (uint32_t builtId = 0; builtId < static_cast(Builtin::COUNT); builtId++) { - testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId)); + testDevice.getBuiltinFunctionsLib()->initBuiltinKernel(static_cast(builtId), false); } EXPECT_EQ(ModuleType::Builtin, testDevice.typeCreated); diff --git a/level_zero/core/test/unit_tests/sources/builtin/create_ult_builtin_functions_lib.cpp b/level_zero/core/test/unit_tests/sources/builtin/create_ult_builtin_functions_lib.cpp index 58fdb9ec01..d3441ebbaa 100644 --- a/level_zero/core/test/unit_tests/sources/builtin/create_ult_builtin_functions_lib.cpp +++ b/level_zero/core/test/unit_tests/sources/builtin/create_ult_builtin_functions_lib.cpp @@ -7,6 +7,7 @@ #include "shared/source/built_ins/built_ins.h" #include "shared/source/compiler_interface/compiler_cache.h" +#include "shared/test/common/helpers/ult_hw_config.h" #include "level_zero/core/source/builtin/builtin_functions_lib_impl.h" #include "level_zero/core/test/unit_tests/mocks/mock_builtin_functions_lib_impl.h" @@ -18,4 +19,8 @@ std::unique_ptr BuiltinFunctionsLib::create(Device *device, return std::unique_ptr(new ult::MockBuiltinFunctionsLibImpl(device, builtins)); } +bool BuiltinFunctionsLibImpl::initBuiltinsAsyncEnabled() { + return NEO::ultHwConfig.useinitBuiltinsAsyncEnabled; +} + } // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp index 416f79d93c..584326b972 100644 --- a/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp +++ b/level_zero/core/test/unit_tests/sources/cmdlist/test_cmdlist_5.cpp @@ -28,7 +28,7 @@ using CommandListCreate = Test; HWTEST_F(CommandListCreate, givenCommandListWithInvalidWaitEventArgWhenAppendQueryKernelTimestampsThenProperErrorRetruned) { ze_result_t returnValue; std::unique_ptr commandList(CommandList::create(productFamily, device, NEO::EngineGroupType::RenderCompute, 0u, returnValue)); - device->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps); + device->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps, false); MockEvent event; event.waitScope = ZE_EVENT_SCOPE_FLAG_HOST; event.signalScope = ZE_EVENT_SCOPE_FLAG_HOST; @@ -50,8 +50,8 @@ using AppendQueryKernelTimestamps = CommandListCreate; HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTimestampsWithoutOffsetsThenProperBuiltinWasAdded, IsAtLeastSkl) { std::unique_ptr> testDevice = std::unique_ptr>(new MockDeviceForSpv(device->getNEODevice(), device->getNEODevice()->getExecutionEnvironment(), driverHandle.get())); testDevice->builtins.reset(new MockBuiltinFunctionsLibImplTimestamps(testDevice.get(), testDevice->getNEODevice()->getBuiltIns())); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestampsWithOffsets); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps, false); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestampsWithOffsets, false); device = testDevice.get(); @@ -113,8 +113,8 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTime HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTimestampsWithOffsetsThenProperBuiltinWasAdded, IsAtLeastSkl) { std::unique_ptr> testDevice = std::unique_ptr>(new MockDeviceForSpv(device->getNEODevice(), device->getNEODevice()->getExecutionEnvironment(), driverHandle.get())); testDevice->builtins.reset(new MockBuiltinFunctionsLibImplTimestamps(testDevice.get(), testDevice->getNEODevice()->getBuiltIns())); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestampsWithOffsets); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps, false); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestampsWithOffsets, false); device = testDevice.get(); @@ -179,7 +179,7 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTimestampsInUsmHostMemoryWithEventsNumberBiggerThanMaxWorkItemSizeThenProperGroupSizeAndGroupCountIsSet, IsAtLeastSkl) { std::unique_ptr> testDevice = std::unique_ptr>(new MockDeviceForSpv(device->getNEODevice(), device->getNEODevice()->getExecutionEnvironment(), driverHandle.get())); testDevice->builtins.reset(new MockBuiltinFunctionsLibImplTimestamps(testDevice.get(), testDevice->getNEODevice()->getBuiltIns())); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps, false); device = testDevice.get(); @@ -237,7 +237,7 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTimestampsInExternalHostMemoryWithEventsNumberBiggerThanMaxWorkItemSizeThenProperGroupSizeAndGroupCountIsSet, IsAtLeastSkl) { std::unique_ptr> testDevice = std::unique_ptr>(new MockDeviceForSpv(device->getNEODevice(), device->getNEODevice()->getExecutionEnvironment(), driverHandle.get())); testDevice->builtins.reset(new MockBuiltinFunctionsLibImplTimestamps(testDevice.get(), testDevice->getNEODevice()->getBuiltIns())); - testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps); + testDevice->getBuiltinFunctionsLib()->initBuiltinKernel(L0::Builtin::QueryKernelTimestamps, false); device = testDevice.get(); @@ -329,7 +329,7 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTime neoDevice->incRefInternal(); execEnvironment = device->getExecEnvironment(); driverHandle = device->getDriverHandle(); - tmpMockBultinLib = new MockBuiltinFunctionsForQueryKernelTimestamps{nullptr, nullptr}; + tmpMockBultinLib = new MockBuiltinFunctionsForQueryKernelTimestamps{this, device->getNEODevice()->getBuiltIns()}; } MockBuiltinFunctionsForQueryKernelTimestamps *getBuiltinFunctionsLib() override { return tmpMockBultinLib; @@ -414,7 +414,7 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenCommandListWhenAppendQueryKernelTime neoDevice->incRefInternal(); execEnvironment = device->getExecEnvironment(); driverHandle = device->getDriverHandle(); - tmpMockBultinLib = new MockBuiltinFunctionsForQueryKernelTimestamps{nullptr, nullptr}; + tmpMockBultinLib = new MockBuiltinFunctionsForQueryKernelTimestamps{this, device->getNEODevice()->getBuiltIns()}; } MockBuiltinFunctionsForQueryKernelTimestamps *getBuiltinFunctionsLib() override { return tmpMockBultinLib; @@ -498,7 +498,7 @@ HWTEST2_F(AppendQueryKernelTimestamps, givenEventWhenAppendQueryIsCalledThenSetA neoDevice->incRefInternal(); execEnvironment = device->getExecEnvironment(); driverHandle = device->getDriverHandle(); - tmpMockBultinLib = std::make_unique(this, nullptr); + tmpMockBultinLib = std::make_unique(this, device->getNEODevice()->getBuiltIns()); } MockBuiltinFunctionsForQueryKernelTimestamps *getBuiltinFunctionsLib() override { return tmpMockBultinLib.get(); diff --git a/level_zero/tools/test/unit_tests/CMakeLists.txt b/level_zero/tools/test/unit_tests/CMakeLists.txt index 5247e89e39..5951ff7566 100644 --- a/level_zero/tools/test/unit_tests/CMakeLists.txt +++ b/level_zero/tools/test/unit_tests/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2020-2022 Intel Corporation +# Copyright (C) 2020-2023 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -27,7 +27,7 @@ target_sources(${TARGET_NAME} PRIVATE ${NEO_SOURCE_DIR}/level_zero/core/test/unit_tests/main.cpp ${NEO_SOURCE_DIR}/level_zero/core/test/unit_tests/mock.h ${NEO_SOURCE_DIR}/level_zero/core/test/unit_tests/white_box.h - ${NEO_SOURCE_DIR}/level_zero/core/source/dll/create_builtin_functions_lib.cpp + ${NEO_SOURCE_DIR}/level_zero/core/test/unit_tests/sources/builtin/create_ult_builtin_functions_lib.cpp ${NEO_SOURCE_DIR}/level_zero/tools/test/unit_tests/sources/debug/debug_session_helper.cpp ${NEO_SHARED_TEST_DIRECTORY}/common/tests_configuration.h ) diff --git a/shared/test/common/base_ult_config_listener.cpp b/shared/test/common/base_ult_config_listener.cpp index 9bd2cba169..8d54f6b5bb 100644 --- a/shared/test/common/base_ult_config_listener.cpp +++ b/shared/test/common/base_ult_config_listener.cpp @@ -36,7 +36,7 @@ void NEO::BaseUltConfigListener::OnTestEnd(const ::testing::TestInfo &) { // Ensure that global state is restored UltHwConfig expectedState{}; - static_assert(sizeof(UltHwConfig) == 14 * sizeof(bool), ""); // Ensure that there is no internal padding + static_assert(sizeof(UltHwConfig) == 15 * sizeof(bool), ""); // Ensure that there is no internal padding EXPECT_EQ(0, memcmp(&expectedState, &ultHwConfig, sizeof(UltHwConfig))); EXPECT_EQ(0, memcmp(&referencedHwInfo.platform, &defaultHwInfo->platform, sizeof(PLATFORM))); diff --git a/shared/test/common/helpers/ult_hw_config.h b/shared/test/common/helpers/ult_hw_config.h index 60790d3b58..4c4298d429 100644 --- a/shared/test/common/helpers/ult_hw_config.h +++ b/shared/test/common/helpers/ult_hw_config.h @@ -12,6 +12,7 @@ struct UltHwConfig { bool useHwCsr = false; bool useMockedPrepareDeviceEnvironmentsFunc = true; bool forceOsAgnosticMemoryManager = true; + bool useinitBuiltinsAsyncEnabled = false; bool useWaitForTimestamps = false; bool useBlitSplit = false; bool useFirstSubmissionInitDevice = false;