diff --git a/level_zero/api/sysman/zes_handles_struct.h b/level_zero/api/sysman/zes_handles_struct.h index 8cc35f8242..a416f23b91 100644 --- a/level_zero/api/sysman/zes_handles_struct.h +++ b/level_zero/api/sysman/zes_handles_struct.h @@ -19,3 +19,7 @@ struct _zes_mem_handle_t { struct _zes_pwr_handle_t { virtual ~_zes_pwr_handle_t() = default; }; + +struct _zes_engine_handle_t { + virtual ~_zes_engine_handle_t() = default; +}; diff --git a/level_zero/api/sysman/zes_sysman_api_entrypoints.h b/level_zero/api/sysman/zes_sysman_api_entrypoints.h index 6a0dcedbe4..892d336699 100644 --- a/level_zero/api/sysman/zes_sysman_api_entrypoints.h +++ b/level_zero/api/sysman/zes_sysman_api_entrypoints.h @@ -364,19 +364,31 @@ ze_result_t zesDeviceEnumEngineGroups( zes_device_handle_t hDevice, uint32_t *pCount, zes_engine_handle_t *phEngine) { - return L0::SysmanDevice::engineGet(hDevice, pCount, phEngine); + if (L0::sysmanInitFromCore) { + return L0::SysmanDevice::engineGet(hDevice, pCount, phEngine); + } else { + return L0::Sysman::SysmanDevice::engineGet(hDevice, pCount, phEngine); + } } ze_result_t zesEngineGetProperties( zes_engine_handle_t hEngine, zes_engine_properties_t *pProperties) { - return L0::Engine::fromHandle(hEngine)->engineGetProperties(pProperties); + if (L0::sysmanInitFromCore) { + return L0::Engine::fromHandle(hEngine)->engineGetProperties(pProperties); + } else { + return L0::Sysman::Engine::fromHandle(hEngine)->engineGetProperties(pProperties); + } } ze_result_t zesEngineGetActivity( zes_engine_handle_t hEngine, zes_engine_stats_t *pStats) { - return L0::Engine::fromHandle(hEngine)->engineGetActivity(pStats); + if (L0::sysmanInitFromCore) { + return L0::Engine::fromHandle(hEngine)->engineGetActivity(pStats); + } else { + return L0::Sysman::Engine::fromHandle(hEngine)->engineGetActivity(pStats); + } } ze_result_t zesDeviceEnumStandbyDomains( diff --git a/level_zero/sysman/source/engine/CMakeLists.txt b/level_zero/sysman/source/engine/CMakeLists.txt new file mode 100755 index 0000000000..dfa18cc569 --- /dev/null +++ b/level_zero/sysman/source/engine/CMakeLists.txt @@ -0,0 +1,24 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_SRCS_SYSMAN_ENGINE + ${CMAKE_CURRENT_SOURCE_DIR}/engine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/engine.h + ${CMAKE_CURRENT_SOURCE_DIR}/engine_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/engine_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine.h +) + +target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${L0_SRCS_SYSMAN_ENGINE} + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt +) + +add_subdirectories() + +# Make our source files visible to parent +set_property(GLOBAL PROPERTY L0_SRCS_SYSMAN_ENGINE ${L0_SRCS_SYSMAN_ENGINE}) diff --git a/level_zero/sysman/source/engine/engine.cpp b/level_zero/sysman/source/engine/engine.cpp new file mode 100644 index 0000000000..9f8edfb376 --- /dev/null +++ b/level_zero/sysman/source/engine/engine.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/engine/engine.h" + +#include "shared/source/helpers/basic_math.h" + +#include "level_zero/sysman/source/engine/engine_imp.h" +#include "level_zero/sysman/source/os_sysman.h" +#include "level_zero/sysman/source/sysman_device_imp.h" + +namespace L0 { +namespace Sysman { + +EngineHandleContext::EngineHandleContext(OsSysman *pOsSysman) { + this->pOsSysman = pOsSysman; +} + +EngineHandleContext::~EngineHandleContext() { + releaseEngines(); +} + +void EngineHandleContext::createHandle(zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubdevice) { + Engine *pEngine = new EngineImp(pOsSysman, engineType, engineInstance, subDeviceId, onSubdevice); + if (pEngine->initSuccess == true) { + handleList.push_back(pEngine); + } else { + delete pEngine; + } +} + +void EngineHandleContext::init(uint32_t subDeviceCount) { + std::set> engineGroupInstance = {}; // set contains pair of engine group and struct containing engine instance and subdeviceId + OsEngine::getNumEngineTypeAndInstances(engineGroupInstance, pOsSysman); + for (auto itr = engineGroupInstance.begin(); itr != engineGroupInstance.end(); ++itr) { + for (uint32_t subDeviceId = 0; subDeviceId <= subDeviceCount; subDeviceId++) { + if (subDeviceId == itr->second.second) { + const auto isSubDevice = subDeviceCount > 0; + createHandle(itr->first, itr->second.first, subDeviceId, isSubDevice); + } + } + } +} + +void EngineHandleContext::releaseEngines() { + for (Engine *pEngine : handleList) { + delete pEngine; + } + handleList.clear(); +} + +ze_result_t EngineHandleContext::engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine) { + std::call_once(initEngineOnce, [this]() { + this->init(pOsSysman->getSubDeviceCount()); + this->engineInitDone = true; + }); + uint32_t handleListSize = static_cast(handleList.size()); + uint32_t numToCopy = std::min(*pCount, handleListSize); + if (0 == *pCount || *pCount > handleListSize) { + *pCount = handleListSize; + } + if (nullptr != phEngine) { + for (uint32_t i = 0; i < numToCopy; i++) { + phEngine[i] = handleList[i]->toHandle(); + } + } + return ZE_RESULT_SUCCESS; +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/engine.h b/level_zero/sysman/source/engine/engine.h new file mode 100644 index 0000000000..2a23b4bf16 --- /dev/null +++ b/level_zero/sysman/source/engine/engine.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "level_zero/api/sysman/zes_handles_struct.h" +#include "level_zero/sysman/source/sysman_device.h" +#include + +#include +#include +#include + +namespace L0 { +namespace Sysman { +using EngineInstanceSubDeviceId = std::pair; +struct OsSysman; + +class Engine : _zes_engine_handle_t { + public: + virtual ze_result_t engineGetProperties(zes_engine_properties_t *pProperties) = 0; + virtual ze_result_t engineGetActivity(zes_engine_stats_t *pStats) = 0; + + static Engine *fromHandle(zes_engine_handle_t handle) { + return static_cast(handle); + } + inline zes_engine_handle_t toHandle() { return this; } + bool initSuccess = false; +}; + +struct EngineHandleContext { + EngineHandleContext(OsSysman *pOsSysman); + virtual ~EngineHandleContext(); + MOCKABLE_VIRTUAL void init(uint32_t subDeviceCount); + void releaseEngines(); + + ze_result_t engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine); + + OsSysman *pOsSysman = nullptr; + std::vector handleList = {}; + bool isEngineInitDone() { + return engineInitDone; + } + + private: + void createHandle(zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubdevice); + std::once_flag initEngineOnce; + bool engineInitDone = false; +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/engine_imp.cpp b/level_zero/sysman/source/engine/engine_imp.cpp new file mode 100644 index 0000000000..bf439f4ad5 --- /dev/null +++ b/level_zero/sysman/source/engine/engine_imp.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/engine/engine_imp.h" + +namespace L0 { +namespace Sysman { + +ze_result_t EngineImp::engineGetActivity(zes_engine_stats_t *pStats) { + return pOsEngine->getActivity(pStats); +} + +ze_result_t EngineImp::engineGetProperties(zes_engine_properties_t *pProperties) { + *pProperties = engineProperties; + return ZE_RESULT_SUCCESS; +} + +void EngineImp::init() { + if (pOsEngine->isEngineModuleSupported()) { + pOsEngine->getProperties(engineProperties); + this->initSuccess = true; + } +} + +EngineImp::EngineImp(OsSysman *pOsSysman, zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubdevice) { + pOsEngine = OsEngine::create(pOsSysman, engineType, engineInstance, subDeviceId, onSubdevice); + init(); +} + +EngineImp::~EngineImp() { + if (nullptr != pOsEngine) { + delete pOsEngine; + pOsEngine = nullptr; + } +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/engine_imp.h b/level_zero/sysman/source/engine/engine_imp.h new file mode 100644 index 0000000000..9c94d99534 --- /dev/null +++ b/level_zero/sysman/source/engine/engine_imp.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/sysman/source/engine/engine.h" +#include "level_zero/sysman/source/engine/os_engine.h" +#include +namespace L0 { +namespace Sysman { + +class EngineImp : public Engine, NEO::NonCopyableOrMovableClass { + public: + ze_result_t engineGetProperties(zes_engine_properties_t *pProperties) override; + ze_result_t engineGetActivity(zes_engine_stats_t *pStats) override; + + EngineImp() = default; + EngineImp(OsSysman *pOsSysman, zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubdevice); + ~EngineImp() override; + + OsEngine *pOsEngine = nullptr; + void init(); + + private: + zes_engine_properties_t engineProperties = {}; +}; +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/linux/CMakeLists.txt b/level_zero/sysman/source/engine/linux/CMakeLists.txt new file mode 100755 index 0000000000..ba5283d720 --- /dev/null +++ b/level_zero/sysman/source/engine/linux/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_SRCS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine_imp.h +) + +if(NEO_ENABLE_i915_PRELIM_DETECTION) + list(APPEND L0_SRCS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine_imp_prelim.cpp + ) +else() + list(APPEND L0_SRCS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine_imp.cpp + ) +endif() + +if(UNIX) + target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${L0_SRCS_SYSMAN_ENGINE_LINUX} + ) +endif() + +# Make our source files visible to parent +set_property(GLOBAL PROPERTY L0_SRCS_SYSMAN_ENGINE_LINUX ${L0_SRCS_SYSMAN_ENGINE_LINUX}) diff --git a/level_zero/sysman/source/engine/linux/os_engine_imp.cpp b/level_zero/sysman/source/engine/linux/os_engine_imp.cpp new file mode 100644 index 0000000000..aea765041d --- /dev/null +++ b/level_zero/sysman/source/engine/linux/os_engine_imp.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/engine/linux/os_engine_imp.h" + +#include "shared/source/debug_settings/debug_settings_manager.h" +#include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/i915.h" + +#include "level_zero/sysman/source/linux/hw_device_id_linux.h" +#include "level_zero/sysman/source/linux/os_sysman_imp.h" +#include "level_zero/sysman/source/linux/pmu/pmu_imp.h" +#include "level_zero/sysman/source/sysman_const.h" + +namespace L0 { +namespace Sysman { + +constexpr auto I915_SAMPLE_BUSY = NEO::I915::drm_i915_pmu_engine_sample::I915_SAMPLE_BUSY; +static const std::multimap<__u16, zes_engine_group_t> i915ToEngineMap = { + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER), ZES_ENGINE_GROUP_RENDER_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO), ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO), ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY), ZES_ENGINE_GROUP_COPY_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE), ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE}}; + +static const std::multimap engineToI915Map = { + {ZES_ENGINE_GROUP_RENDER_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER)}, + {ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO)}, + {ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO)}, + {ZES_ENGINE_GROUP_COPY_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY)}, + {ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE)}}; + +ze_result_t OsEngine::getNumEngineTypeAndInstances(std::set> &engineGroupInstance, OsSysman *pOsSysman) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + NEO::Drm *pDrm = pLinuxSysmanImp->getDrm(); + auto hwDeviceId = pLinuxSysmanImp->getSysmanHwDeviceId(); + + hwDeviceId->openFileDescriptor(); + auto status = pDrm->sysmanQueryEngineInfo(); + hwDeviceId->closeFileDescriptor(); + + if (status == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():sysmanQueryEngineInfo is returning false and error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + auto engineInfo = pDrm->getEngineInfo(); + for (auto itr = engineInfo->engines.begin(); itr != engineInfo->engines.end(); ++itr) { + auto i915ToEngineMapRange = i915ToEngineMap.equal_range(static_cast<__u16>(itr->engine.engineClass)); + for (auto l0EngineEntryInMap = i915ToEngineMapRange.first; l0EngineEntryInMap != i915ToEngineMapRange.second; l0EngineEntryInMap++) { + auto l0EngineType = l0EngineEntryInMap->second; + engineGroupInstance.insert({l0EngineType, {static_cast(itr->engine.engineInstance), 0}}); + } + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxEngineImp::getActivity(zes_engine_stats_t *pStats) { + if (fd < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d it's returning error:0x%x \n", __FUNCTION__, fd, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + uint64_t data[2] = {}; + auto ret = pPmuInterface->pmuRead(static_cast(fd), data, sizeof(data)); + if (ret < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():pmuRead is returning value:%d and error:0x%x \n", __FUNCTION__, ret, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + // In data[], First u64 is "active time", And second u64 is "timestamp". Both in nanoseconds + pStats->activeTime = data[0] / microSecondsToNanoSeconds; + pStats->timestamp = data[1] / microSecondsToNanoSeconds; + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxEngineImp::getProperties(zes_engine_properties_t &properties) { + properties.type = engineGroup; + properties.onSubdevice = onSubDevice; + properties.subdeviceId = subDeviceId; + return ZE_RESULT_SUCCESS; +} + +void LinuxEngineImp::init() { + auto i915EngineClass = engineToI915Map.find(engineGroup); + // I915_PMU_ENGINE_BUSY macro provides the perf type config which we want to listen to get the engine busyness. + fd = pPmuInterface->pmuInterfaceOpen(I915_PMU_ENGINE_BUSY(i915EngineClass->second, engineInstance), -1, PERF_FORMAT_TOTAL_TIME_ENABLED); +} + +bool LinuxEngineImp::isEngineModuleSupported() { + if (fd < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d Engine Module is not supported \n", __FUNCTION__, fd); + return false; + } + return true; +} + +LinuxEngineImp::LinuxEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) : engineGroup(type), engineInstance(engineInstance), subDeviceId(subDeviceId), onSubDevice(onSubDevice) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + pDrm = pLinuxSysmanImp->getDrm(); + pDevice = pLinuxSysmanImp->getSysmanDeviceImp(); + pPmuInterface = pLinuxSysmanImp->getPmuInterface(); + init(); +} + +OsEngine *OsEngine::create(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) { + LinuxEngineImp *pLinuxEngineImp = new LinuxEngineImp(pOsSysman, type, engineInstance, subDeviceId, onSubDevice); + return static_cast(pLinuxEngineImp); +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/linux/os_engine_imp.h b/level_zero/sysman/source/engine/linux/os_engine_imp.h new file mode 100644 index 0000000000..acd832bb91 --- /dev/null +++ b/level_zero/sysman/source/engine/linux/os_engine_imp.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" +#include "shared/source/os_interface/linux/drm_neo.h" + +#include "level_zero/sysman/source/engine/os_engine.h" +#include "level_zero/sysman/source/sysman_device_imp.h" + +#include + +namespace L0 { +namespace Sysman { + +class PmuInterface; +struct Device; +class LinuxEngineImp : public OsEngine, NEO::NonCopyableOrMovableClass { + public: + ze_result_t getActivity(zes_engine_stats_t *pStats) override; + ze_result_t getProperties(zes_engine_properties_t &properties) override; + bool isEngineModuleSupported() override; + static zes_engine_group_t getGroupFromEngineType(zes_engine_group_t type); + LinuxEngineImp() = default; + LinuxEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice); + ~LinuxEngineImp() override { + if (fd != -1) { + close(static_cast(fd)); + fd = -1; + } + } + + protected: + zes_engine_group_t engineGroup = ZES_ENGINE_GROUP_ALL; + uint32_t engineInstance = 0; + PmuInterface *pPmuInterface = nullptr; + NEO::Drm *pDrm = nullptr; + SysmanDeviceImp *pDevice = nullptr; + uint32_t subDeviceId = 0; + ze_bool_t onSubDevice = false; + + private: + void init(); + int64_t fd = -1; +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/linux/os_engine_imp_prelim.cpp b/level_zero/sysman/source/engine/linux/os_engine_imp_prelim.cpp new file mode 100644 index 0000000000..36fd861c21 --- /dev/null +++ b/level_zero/sysman/source/engine/linux/os_engine_imp_prelim.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2022-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/debug_settings/debug_settings_manager.h" +#include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/i915_prelim.h" + +#include "level_zero/sysman/source/engine/linux/os_engine_imp.h" +#include "level_zero/sysman/source/linux/hw_device_id_linux.h" +#include "level_zero/sysman/source/linux/os_sysman_imp.h" +#include "level_zero/sysman/source/linux/pmu/pmu_imp.h" +#include "level_zero/sysman/source/sysman_const.h" + +namespace L0 { +namespace Sysman { + +using NEO::PrelimI915::I915_SAMPLE_BUSY; + +static const std::multimap<__u16, zes_engine_group_t> i915ToEngineMap = { + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER), ZES_ENGINE_GROUP_RENDER_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO), ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO), ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY), ZES_ENGINE_GROUP_COPY_SINGLE}, + {static_cast<__u16>(prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE), ZES_ENGINE_GROUP_COMPUTE_SINGLE}, + {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE), ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE}}; + +static const std::multimap engineToI915Map = { + {ZES_ENGINE_GROUP_RENDER_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER)}, + {ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO)}, + {ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO)}, + {ZES_ENGINE_GROUP_COPY_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY)}, + {ZES_ENGINE_GROUP_COMPUTE_SINGLE, static_cast<__u16>(prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE)}, + {ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE, static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE)}}; + +zes_engine_group_t LinuxEngineImp::getGroupFromEngineType(zes_engine_group_t type) { + if (type == ZES_ENGINE_GROUP_RENDER_SINGLE) { + return ZES_ENGINE_GROUP_RENDER_ALL; + } + if (type == ZES_ENGINE_GROUP_COMPUTE_SINGLE) { + return ZES_ENGINE_GROUP_COMPUTE_ALL; + } + if (type == ZES_ENGINE_GROUP_COPY_SINGLE) { + return ZES_ENGINE_GROUP_COPY_ALL; + } + if (type == ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE || type == ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE || type == ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE) { + return ZES_ENGINE_GROUP_MEDIA_ALL; + } + return ZES_ENGINE_GROUP_ALL; +} + +ze_result_t OsEngine::getNumEngineTypeAndInstances(std::set> &engineGroupInstance, OsSysman *pOsSysman) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + NEO::Drm *pDrm = pLinuxSysmanImp->getDrm(); + auto hwDeviceId = pLinuxSysmanImp->getSysmanHwDeviceId(); + + hwDeviceId->openFileDescriptor(); + auto status = pDrm->sysmanQueryEngineInfo(); + hwDeviceId->closeFileDescriptor(); + + if (status == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():sysmanQueryEngineInfo is returning false and error message:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + auto engineInfo = pDrm->getEngineInfo(); + for (auto itr = engineInfo->engines.begin(); itr != engineInfo->engines.end(); ++itr) { + uint32_t subDeviceId = engineInfo->getEngineTileIndex(itr->engine); + auto i915ToEngineMapRange = i915ToEngineMap.equal_range(static_cast<__u16>(itr->engine.engineClass)); + for (auto l0EngineEntryInMap = i915ToEngineMapRange.first; l0EngineEntryInMap != i915ToEngineMapRange.second; l0EngineEntryInMap++) { + auto l0EngineType = l0EngineEntryInMap->second; + engineGroupInstance.insert({l0EngineType, {static_cast(itr->engine.engineInstance), subDeviceId}}); + engineGroupInstance.insert({LinuxEngineImp::getGroupFromEngineType(l0EngineType), {0u, subDeviceId}}); + engineGroupInstance.insert({ZES_ENGINE_GROUP_ALL, {0u, subDeviceId}}); + } + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxEngineImp::getActivity(zes_engine_stats_t *pStats) { + if (fd < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d it's returning error:0x%x \n", __FUNCTION__, fd, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + uint64_t data[2] = {}; + auto ret = pPmuInterface->pmuRead(static_cast(fd), data, sizeof(data)); + if (ret < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():pmuRead is returning value:%d and error:0x%x \n", __FUNCTION__, ret, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + // In data[], First u64 is "active time", And second u64 is "timestamp". Both in nanoseconds + pStats->activeTime = data[0] / microSecondsToNanoSeconds; + pStats->timestamp = data[1] / microSecondsToNanoSeconds; + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxEngineImp::getProperties(zes_engine_properties_t &properties) { + properties.subdeviceId = subDeviceId; + properties.onSubdevice = onSubDevice; + properties.type = engineGroup; + return ZE_RESULT_SUCCESS; +} + +void LinuxEngineImp::init() { + uint64_t config = UINT64_MAX; + switch (engineGroup) { + case ZES_ENGINE_GROUP_ALL: + config = __PRELIM_I915_PMU_ANY_ENGINE_GROUP_BUSY(subDeviceId); + break; + case ZES_ENGINE_GROUP_COMPUTE_ALL: + case ZES_ENGINE_GROUP_RENDER_ALL: + config = __PRELIM_I915_PMU_RENDER_GROUP_BUSY(subDeviceId); + break; + case ZES_ENGINE_GROUP_COPY_ALL: + config = __PRELIM_I915_PMU_COPY_GROUP_BUSY(subDeviceId); + break; + case ZES_ENGINE_GROUP_MEDIA_ALL: + config = __PRELIM_I915_PMU_MEDIA_GROUP_BUSY(subDeviceId); + break; + default: + auto i915EngineClass = engineToI915Map.find(engineGroup); + config = I915_PMU_ENGINE_BUSY(i915EngineClass->second, engineInstance); + break; + } + fd = pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED); +} + +bool LinuxEngineImp::isEngineModuleSupported() { + if (fd < 0) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d Engine Module is not supported \n", __FUNCTION__, fd); + return false; + } + return true; +} + +LinuxEngineImp::LinuxEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) : engineGroup(type), engineInstance(engineInstance), subDeviceId(subDeviceId), onSubDevice(onSubDevice) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + pDrm = pLinuxSysmanImp->getDrm(); + pDevice = pLinuxSysmanImp->getSysmanDeviceImp(); + pPmuInterface = pLinuxSysmanImp->getPmuInterface(); + init(); +} + +OsEngine *OsEngine::create(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) { + LinuxEngineImp *pLinuxEngineImp = new LinuxEngineImp(pOsSysman, type, engineInstance, subDeviceId, onSubDevice); + return static_cast(pLinuxEngineImp); +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/os_engine.h b/level_zero/sysman/source/engine/os_engine.h new file mode 100644 index 0000000000..eaccd02760 --- /dev/null +++ b/level_zero/sysman/source/engine/os_engine.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "level_zero/sysman/source/engine/engine.h" +#include + +#include + +namespace L0 { +namespace Sysman { + +struct OsSysman; + +class OsEngine { + public: + virtual ze_result_t getActivity(zes_engine_stats_t *pStats) = 0; + virtual ze_result_t getProperties(zes_engine_properties_t &properties) = 0; + virtual bool isEngineModuleSupported() = 0; + static OsEngine *create(OsSysman *pOsSysman, zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubdevice); + static ze_result_t getNumEngineTypeAndInstances(std::set> &engineGroupInstance, OsSysman *pOsSysman); + virtual ~OsEngine() = default; +}; + +} // namespace Sysman + +} // namespace L0 diff --git a/level_zero/sysman/source/engine/windows/CMakeLists.txt b/level_zero/sysman/source/engine/windows/CMakeLists.txt new file mode 100755 index 0000000000..8b5ee7215d --- /dev/null +++ b/level_zero/sysman/source/engine/windows/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_SRCS_TOOLS_SYSMAN_ENGINE_WINDOWS + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/os_engine_imp.cpp +) + +if(WIN32) + target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${L0_SRCS_TOOLS_SYSMAN_ENGINE_WINDOWS} + ) +endif() + +# Make our source files visible to parent +set_property(GLOBAL PROPERTY L0_SRCS_TOOLS_SYSMAN_ENGINE_WINDOWS ${L0_SRCS_TOOLS_SYSMAN_ENGINE_WINDOWS}) diff --git a/level_zero/sysman/source/engine/windows/os_engine_imp.cpp b/level_zero/sysman/source/engine/windows/os_engine_imp.cpp new file mode 100644 index 0000000000..ee7d94d728 --- /dev/null +++ b/level_zero/sysman/source/engine/windows/os_engine_imp.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/engine/windows/os_engine_imp.h" + +namespace L0 { +namespace Sysman { + +OsEngine *OsEngine::create(OsSysman *pOsSysman, zes_engine_group_t engineType, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) { + WddmEngineImp *pWddmEngineImp = new WddmEngineImp(pOsSysman, engineType, engineInstance, subDeviceId); + return static_cast(pWddmEngineImp); +} + +ze_result_t OsEngine::getNumEngineTypeAndInstances(std::set> &engineGroupInstance, OsSysman *pOsSysman) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/engine/windows/os_engine_imp.h b/level_zero/sysman/source/engine/windows/os_engine_imp.h new file mode 100644 index 0000000000..6712b18b4e --- /dev/null +++ b/level_zero/sysman/source/engine/windows/os_engine_imp.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/sysman/source/engine/os_engine.h" +#include "level_zero/sysman/source/windows/os_sysman_imp.h" + +namespace L0 { +namespace Sysman { +class WddmEngineImp : public OsEngine, NEO::NonCopyableOrMovableClass { + public: + ze_result_t getActivity(zes_engine_stats_t *pStats) override { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } + ze_result_t getProperties(zes_engine_properties_t &properties) override { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; }; + bool isEngineModuleSupported() override { return false; }; + + WddmEngineImp() = default; + WddmEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId) {} + ~WddmEngineImp() override = default; +}; +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/sysman_device.cpp b/level_zero/sysman/source/sysman_device.cpp index 30dd28af7e..815b84b485 100644 --- a/level_zero/sysman/source/sysman_device.cpp +++ b/level_zero/sysman/source/sysman_device.cpp @@ -51,5 +51,10 @@ ze_result_t SysmanDevice::powerGetCardDomain(zes_device_handle_t hDevice, zes_pw return pSysmanDevice->powerGetCardDomain(phPower); } +ze_result_t SysmanDevice::engineGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_engine_handle_t *phEngine) { + auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice); + return pSysmanDevice->engineGet(pCount, phEngine); +} + } // namespace Sysman } // namespace L0 diff --git a/level_zero/sysman/source/sysman_device.h b/level_zero/sysman/source/sysman_device.h index 914ccf0488..139b2f9bd6 100644 --- a/level_zero/sysman/source/sysman_device.h +++ b/level_zero/sysman/source/sysman_device.h @@ -9,6 +9,7 @@ #include "shared/source/execution_environment/execution_environment.h" #include "level_zero/core/source/device/device.h" +#include "level_zero/sysman/source/engine/engine.h" #include "level_zero/sysman/source/fabric_port/fabric_port.h" #include "level_zero/sysman/source/memory/memory.h" #include "level_zero/sysman/source/power/power.h" @@ -36,6 +37,9 @@ struct SysmanDevice : _ze_device_handle_t { virtual ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) = 0; static ze_result_t memoryGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_mem_handle_t *phMemory); virtual ze_result_t memoryGet(uint32_t *pCount, zes_mem_handle_t *phMemory) = 0; + + static ze_result_t engineGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_engine_handle_t *phEngine); + virtual ze_result_t engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine) = 0; }; } // namespace Sysman diff --git a/level_zero/sysman/source/sysman_device_imp.cpp b/level_zero/sysman/source/sysman_device_imp.cpp index 61379dc6c4..3a671c8c0a 100644 --- a/level_zero/sysman/source/sysman_device_imp.cpp +++ b/level_zero/sysman/source/sysman_device_imp.cpp @@ -24,11 +24,13 @@ SysmanDeviceImp::SysmanDeviceImp(NEO::ExecutionEnvironment *executionEnvironment pFabricPortHandleContext = new FabricPortHandleContext(pOsSysman); pMemoryHandleContext = new MemoryHandleContext(pOsSysman); pPowerHandleContext = new PowerHandleContext(pOsSysman); + pEngineHandleContext = new EngineHandleContext(pOsSysman); } SysmanDeviceImp::~SysmanDeviceImp() { executionEnvironment->decRefInternal(); freeResource(pPowerHandleContext); + freeResource(pEngineHandleContext); freeResource(pFabricPortHandleContext); freeResource(pMemoryHandleContext); freeResource(pOsSysman); @@ -58,5 +60,9 @@ ze_result_t SysmanDeviceImp::powerGet(uint32_t *pCount, zes_pwr_handle_t *phPowe return pPowerHandleContext->powerGet(pCount, phPower); } +ze_result_t SysmanDeviceImp::engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine) { + return pEngineHandleContext->engineGet(pCount, phEngine); +} + } // namespace Sysman } // namespace L0 diff --git a/level_zero/sysman/source/sysman_device_imp.h b/level_zero/sysman/source/sysman_device_imp.h index 1b41847d4d..189e37d607 100644 --- a/level_zero/sysman/source/sysman_device_imp.h +++ b/level_zero/sysman/source/sysman_device_imp.h @@ -43,9 +43,11 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass { FabricPortHandleContext *pFabricPortHandleContext = nullptr; MemoryHandleContext *pMemoryHandleContext = nullptr; + EngineHandleContext *pEngineHandleContext = nullptr; - ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) override; ze_result_t memoryGet(uint32_t *pCount, zes_mem_handle_t *phMemory) override; + ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) override; + ze_result_t engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine) override; private: NEO::ExecutionEnvironment *executionEnvironment = nullptr; diff --git a/level_zero/sysman/test/unit_tests/sources/engine/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/engine/CMakeLists.txt new file mode 100644 index 0000000000..ffeb6e3a80 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +target_sources(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt +) + +add_subdirectories() diff --git a/level_zero/sysman/test/unit_tests/sources/engine/linux/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/engine/linux/CMakeLists.txt new file mode 100644 index 0000000000..9fbd352a52 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/linux/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_TESTS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt +) + +if(NEO_ENABLE_i915_PRELIM_DETECTION) + list(APPEND L0_TESTS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_engine_prelim.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_engine_prelim.h + ) + +else() + list(APPEND L0_TESTS_SYSMAN_ENGINE_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_engine.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_engine.h + ) +endif() + +if(UNIX) + target_sources(${TARGET_NAME} + PRIVATE + ${L0_TESTS_SYSMAN_ENGINE_LINUX} + ) +endif() diff --git a/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine.h b/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine.h new file mode 100644 index 0000000000..57df0c45b2 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/i915.h" +#include "shared/test/common/libult/linux/drm_mock.h" + +#include "level_zero/sysman/source/engine/engine_imp.h" +#include "level_zero/sysman/source/engine/linux/os_engine_imp.h" +#include "level_zero/sysman/source/linux/os_sysman_imp.h" +#include "level_zero/sysman/source/linux/pmu/pmu_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h" + +using namespace NEO; +namespace L0 { +namespace ult { +constexpr int64_t mockPmuFd = 10; +constexpr uint64_t mockTimestamp = 87654321; +constexpr uint64_t mockActiveTime = 987654321; +const uint32_t microSecondsToNanoSeconds = 1000u; +constexpr uint16_t I915_INVALID_ENGINE_CLASS = UINT16_MAX; +const std::string deviceDir("device"); + +struct MockEngineNeoDrm : public Drm { + using Drm::getEngineInfo; + using Drm::setupIoctlHelper; + const int mockFd = 0; + MockEngineNeoDrm(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique(mockFd, ""), rootDeviceEnvironment) {} + + bool mockSysmanQueryEngineInfoReturnFalse = true; + bool sysmanQueryEngineInfo() override { + if (mockSysmanQueryEngineInfoReturnFalse != true) { + return mockSysmanQueryEngineInfoReturnFalse; + } + + std::vector i915engineInfo(6); + i915engineInfo[0].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER; + i915engineInfo[0].engine.engineInstance = 0; + i915engineInfo[1].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER; + i915engineInfo[1].engine.engineInstance = 1; + i915engineInfo[2].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO; + i915engineInfo[2].engine.engineInstance = 1; + i915engineInfo[3].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY; + i915engineInfo[3].engine.engineInstance = 0; + i915engineInfo[4].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE; + i915engineInfo[4].engine.engineInstance = 0; + i915engineInfo[5].engine.engineClass = I915_INVALID_ENGINE_CLASS; + i915engineInfo[5].engine.engineInstance = 0; + + this->engineInfo.reset(new EngineInfo(this, i915engineInfo)); + return true; + } +}; + +struct MockEnginePmuInterfaceImp : public L0::Sysman::PmuInterfaceImp { + using PmuInterfaceImp::perfEventOpen; + MockEnginePmuInterfaceImp(L0::Sysman::LinuxSysmanImp *pLinuxSysmanImp) : PmuInterfaceImp(pLinuxSysmanImp) {} + + int64_t mockPerfEventFailureReturnValue = 0; + int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) override { + if (mockPerfEventFailureReturnValue == -1) { + return mockPerfEventFailureReturnValue; + } + + return mockPmuFd; + } + + int mockPmuReadFailureReturnValue = 0; + int pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) override { + if (mockPmuReadFailureReturnValue == -1) { + return mockPmuReadFailureReturnValue; + } + + data[0] = mockActiveTime; + data[1] = mockTimestamp; + return 0; + } +}; + +struct MockEngineFsAccess : public L0::Sysman::FsAccess { + uint32_t mockReadVal = 23; + ze_result_t mockReadErrorVal = ZE_RESULT_SUCCESS; + ze_result_t readResult = ZE_RESULT_SUCCESS; + ze_result_t read(const std::string file, uint32_t &val) override { + val = mockReadVal; + if (mockReadErrorVal != ZE_RESULT_SUCCESS) { + readResult = mockReadErrorVal; + } + + return readResult; + } +}; + +struct MockEngineSysfsAccess : public L0::Sysman::SysfsAccess { + ze_result_t mockReadSymLinkError = ZE_RESULT_SUCCESS; + ze_result_t readSymLinkResult = ZE_RESULT_SUCCESS; + uint32_t readSymLinkCalled = 0u; + ze_result_t readSymLink(const std::string file, std::string &val) override { + readSymLinkCalled++; + if ((mockReadSymLinkError != ZE_RESULT_SUCCESS) && (readSymLinkCalled == 1)) { + return mockReadSymLinkError; + } + + if (file.compare(deviceDir) == 0) { + val = "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0"; + } + return readSymLinkResult; + } + + MockEngineSysfsAccess() = default; +}; + +using DrmMockEngineInfoFailing = DrmMock; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine_prelim.h b/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine_prelim.h new file mode 100644 index 0000000000..703de2fd8a --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine_prelim.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2022-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/i915_prelim.h" + +#include "level_zero/sysman/source/engine/engine_imp.h" +#include "level_zero/sysman/source/engine/linux/os_engine_imp.h" +#include "level_zero/sysman/source/linux/os_sysman_imp.h" +#include "level_zero/sysman/source/linux/pmu/pmu_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h" + +using namespace NEO; +namespace L0 { +namespace ult { +constexpr int64_t mockPmuFd = 10; +constexpr uint64_t mockTimestamp = 87654321; +constexpr uint64_t mockActiveTime = 987654321; +const uint32_t microSecondsToNanoSeconds = 1000u; +constexpr uint16_t I915_INVALID_ENGINE_CLASS = UINT16_MAX; +const std::string deviceDir("device"); +constexpr uint32_t numberOfMockedEnginesForSingleTileDevice = 7u; +constexpr uint32_t numberOfTiles = 2u; +constexpr uint32_t numberOfMockedEnginesForMultiTileDevice = 2u; + +struct MockEngineNeoDrm : public Drm { + using Drm::engineInfo; + using Drm::setupIoctlHelper; + const int mockFd = 0; + MockEngineNeoDrm(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique(mockFd, ""), rootDeviceEnvironment) {} + + bool mockReadSysmanQueryEngineInfo = false; + bool mockReadSysmanQueryEngineInfoMultiDevice = false; + + bool sysmanQueryEngineInfo() override { + + if (mockReadSysmanQueryEngineInfo == true) { + return queryEngineInfoMockReturnFalse(); + } + + if (mockReadSysmanQueryEngineInfoMultiDevice == true) { + return queryEngineInfoForMultiDeviceFixtureMockPositiveTest(); + } + + std::vector i915QueryEngineInfo(numberOfMockedEnginesForSingleTileDevice); + i915QueryEngineInfo[0].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER; + i915QueryEngineInfo[0].engine.engineInstance = 0; + i915QueryEngineInfo[1].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO; + i915QueryEngineInfo[1].engine.engineInstance = 0; + i915QueryEngineInfo[2].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO; + i915QueryEngineInfo[2].engine.engineInstance = 1; + i915QueryEngineInfo[3].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY; + i915QueryEngineInfo[3].engine.engineInstance = 0; + i915QueryEngineInfo[4].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO_ENHANCE; + i915QueryEngineInfo[4].engine.engineInstance = 0; + i915QueryEngineInfo[5].engine.engineClass = PrelimI915::prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE; + i915QueryEngineInfo[5].engine.engineInstance = 0; + i915QueryEngineInfo[6].engine.engineClass = I915_INVALID_ENGINE_CLASS; + i915QueryEngineInfo[6].engine.engineInstance = 0; + + this->engineInfo.reset(new EngineInfo(this, i915QueryEngineInfo)); + return true; + } + + bool queryEngineInfoMockReturnFalse() { + return false; + } + + bool queryEngineInfoForMultiDeviceFixtureMockPositiveTest() { + // Fill distanceInfos vector with dummy values + std::vector distanceInfos = { + {{1, 0}, {drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, 0}, 0}, + {{1, 1}, {drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO, 0}, 0}}; + + std::vector queryItems{distanceInfos.size()}; + for (auto i = 0u; i < distanceInfos.size(); i++) { + queryItems[i].queryId = PRELIM_DRM_I915_QUERY_DISTANCE_INFO; + queryItems[i].length = sizeof(PrelimI915::prelim_drm_i915_query_distance_info); + queryItems[i].flags = 0u; + queryItems[i].dataPtr = reinterpret_cast(&distanceInfos[i]); + } + + // Fill i915QueryEngineInfo with dummy values + std::vector i915QueryEngineInfo(numberOfMockedEnginesForMultiTileDevice); + i915QueryEngineInfo[0].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER; + i915QueryEngineInfo[0].engine.engineInstance = 0; + i915QueryEngineInfo[1].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_VIDEO; + i915QueryEngineInfo[1].engine.engineInstance = 0; + + this->engineInfo.reset(new EngineInfo(this, numberOfTiles, distanceInfos, queryItems, i915QueryEngineInfo)); + return true; + } +}; + +struct MockEnginePmuInterfaceImp : public L0::Sysman::PmuInterfaceImp { + using PmuInterfaceImp::perfEventOpen; + MockEnginePmuInterfaceImp(L0::Sysman::LinuxSysmanImp *pLinuxSysmanImp) : PmuInterfaceImp(pLinuxSysmanImp) {} + + bool mockPmuRead = false; + bool mockPerfEventOpenRead = false; + + int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) override { + + if (mockPerfEventOpenRead == true) { + return mockedPerfEventOpenAndFailureReturn(attr, pid, cpu, groupFd, flags); + } + + return mockPmuFd; + } + + int64_t mockedPerfEventOpenAndFailureReturn(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) { + return -1; + } + + int pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) override { + + if (mockPmuRead == true) { + return mockedPmuReadAndFailureReturn(fd, data, sizeOfdata); + } + + data[0] = mockActiveTime; + data[1] = mockTimestamp; + return 0; + } + + int mockedPmuReadAndFailureReturn(int fd, uint64_t *data, ssize_t sizeOfdata) { + return -1; + } +}; + +struct MockEngineFsAccess : public L0::Sysman::FsAccess { + + bool mockReadVal = false; + + ze_result_t read(const std::string file, uint32_t &val) override { + + if (mockReadVal == true) { + return readValFailure(file, val); + } + + val = 23; + return ZE_RESULT_SUCCESS; + } + + ze_result_t readValFailure(const std::string file, uint32_t &val) { + val = 0; + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } +}; + +struct MockEngineSysfsAccess : public L0::Sysman::SysfsAccess { + + bool mockReadSymLinkFailure = false; + bool mockReadSymLinkSuccess = false; + + ze_result_t readSymLink(const std::string file, std::string &val) override { + + if (mockReadSymLinkFailure == true) { + return getValStringSymLinkFailure(file, val); + } + + if (mockReadSymLinkSuccess == true) { + return getValStringSymLinkSuccess(file, val); + } + + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ze_result_t getValStringSymLinkSuccess(const std::string file, std::string &val) { + + if (file.compare(deviceDir) == 0) { + val = "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0"; + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ze_result_t getValStringSymLinkFailure(const std::string file, std::string &val) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + MockEngineSysfsAccess() = default; +}; +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine.cpp b/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine.cpp new file mode 100644 index 0000000000..7eb8dbfc9b --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/linux/memory_info.h" + +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" + +#include "mock_engine.h" + +namespace L0 { +namespace ult { +constexpr uint32_t handleComponentCount = 6u; +class ZesEngineFixture : public SysmanDeviceFixture { + protected: + std::unique_ptr pPmuInterface; + L0::Sysman::PmuInterface *pOriginalPmuInterface = nullptr; + std::unique_ptr pSysfsAccess; + L0::Sysman::SysfsAccess *pSysfsAccessOriginal = nullptr; + std::unique_ptr pFsAccess; + L0::Sysman::FsAccess *pFsAccessOriginal = nullptr; + L0::Sysman::SysmanDevice *device = nullptr; + + void SetUp() override { + SysmanDeviceFixture::SetUp(); + + pSysfsAccessOriginal = pLinuxSysmanImp->pSysfsAccess; + pSysfsAccess = std::make_unique(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pFsAccess = std::make_unique(); + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + + MockEngineNeoDrm *pDrm = new MockEngineNeoDrm(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterface->setDriverModel(std::unique_ptr(pDrm)); + + pPmuInterface = std::make_unique(pLinuxSysmanImp); + pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface; + pLinuxSysmanImp->pPmuInterface = pPmuInterface.get(); + pFsAccess->mockReadVal = 23; + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = true; + device = pSysmanDevice; + getEngineHandles(0); + } + + void TearDown() override { + pLinuxSysmanImp->pPmuInterface = pOriginalPmuInterface; + pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOriginal; + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + + SysmanDeviceFixture::TearDown(); + } + + std::vector getEngineHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(ZesEngineFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumEngineGroupsThenNonZeroCountIsReturnedAndVerifyCallSucceeds) { + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, handleComponentCount); + + uint32_t testcount = count + 1; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &testcount, NULL)); + EXPECT_EQ(testcount, count); + + count = 0; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, handleComponentCount); +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandlesWhenCallingZesEngineGetPropertiesThenVerifyCallSucceeds) { + zes_engine_properties_t properties; + auto handle = getEngineHandles(handleComponentCount); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[0], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[1], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[2], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[3], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[4], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_COPY_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[5], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndIntegratedDeviceWhenCallingZesEngineGetActivityThenVerifyCallReturnsSuccess) { + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); + EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); + EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + } +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndDiscreteDeviceWhenCallingZesEngineGetActivityThenVerifyCallReturnsSuccess) { + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = false; + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); + EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); + EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + } +} + +TEST_F(ZesEngineFixture, GivenTestDiscreteDevicesAndValidEngineHandleWhenCallingZesEngineGetActivityAndPMUGetEventTypeFailsThenVerifyEngineGetActivityReturnsFailure) { + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = false; + pSysfsAccess->mockReadSymLinkError = ZE_RESULT_ERROR_NOT_AVAILABLE; + auto pOsEngineTest1 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + + zes_engine_stats_t stats = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest1->getActivity(&stats)); + pFsAccess->mockReadVal = 0; + pFsAccess->mockReadErrorVal = ZE_RESULT_ERROR_NOT_AVAILABLE; + + auto pOsEngineTest2 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest2->getActivity(&stats)); + delete pOsEngineTest1; + delete pOsEngineTest2; +} + +TEST_F(ZesEngineFixture, GivenTestIntegratedDevicesAndValidEngineHandleWhenCallingZesEngineGetActivityAndPMUGetEventTypeFailsThenVerifyEngineGetActivityReturnsFailure) { + zes_engine_stats_t stats = {}; + pFsAccess->mockReadVal = 0; + pFsAccess->mockReadErrorVal = ZE_RESULT_ERROR_NOT_AVAILABLE; + + auto pOsEngineTest1 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest1->getActivity(&stats)); + delete pOsEngineTest1; +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleWhenCallingZesEngineGetActivityAndPmuReadFailsThenVerifyEngineGetActivityReturnsFailure) { + pPmuInterface->mockPmuReadFailureReturnValue = -1; + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesEngineGetActivity(handle, &stats)); + } +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleWhenCallingZesEngineGetActivityAndperfEventOpenFailsThenVerifyEngineGetActivityReturnsFailure) { + pPmuInterface->mockPerfEventFailureReturnValue = -1; + MockEnginePmuInterfaceImp pPmuInterfaceImp(pLinuxSysmanImp); + EXPECT_EQ(-1, pPmuInterface->pmuInterfaceOpen(0, -1, 0)); +} + +TEST_F(ZesEngineFixture, GivenValidOsSysmanPointerWhenRetrievingEngineTypeAndInstancesAndIfEngineInfoQueryFailsThenErrorIsReturned) { + std::set> engineGroupInstance; + + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + auto *pDrm = osInterface->getDriverModel()->as(); + pDrm->mockSysmanQueryEngineInfoReturnFalse = false; + + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, L0::Sysman::OsEngine::getNumEngineTypeAndInstances(engineGroupInstance, pOsSysman)); +} + +TEST_F(ZesEngineFixture, givenEngineInfoQuerySupportedWhenQueryingEngineInfoThenEngineInfoIsCreatedWithEngines) { + auto drm = std::make_unique((const_cast(pSysmanDeviceImp->getRootDeviceEnvironment()))); + ASSERT_NE(nullptr, drm); + std::vector memRegions{ + {{drm_i915_gem_memory_class::I915_MEMORY_CLASS_SYSTEM, 0}, 1024, 0}}; + drm->memoryInfo.reset(new MemoryInfo(memRegions, *drm)); + drm->sysmanQueryEngineInfo(); + auto engineInfo = drm->getEngineInfo(); + ASSERT_NE(nullptr, engineInfo); + EXPECT_EQ(2u, engineInfo->engines.size()); +} + +TEST_F(ZesEngineFixture, GivenEngineInfoWithVideoQuerySupportedWhenQueryingEngineInfoWithVideoThenEngineInfoIsCreatedWithEngines) { + auto drm = std::make_unique((const_cast(pSysmanDeviceImp->getRootDeviceEnvironment()))); + ASSERT_NE(nullptr, drm); + std::vector memRegions{ + {{drm_i915_gem_memory_class::I915_MEMORY_CLASS_SYSTEM, 0}, 1024, 0}}; + drm->memoryInfo.reset(new MemoryInfo(memRegions, *drm)); + drm->sysmanQueryEngineInfo(); + auto engineInfo = drm->getEngineInfo(); + ASSERT_NE(nullptr, engineInfo); + EXPECT_EQ(2u, engineInfo->engines.size()); +} + +TEST_F(ZesEngineFixture, GivenEngineInfoWithVideoQueryFailsThenFailureIsReturned) { + auto drm = std::make_unique((const_cast(pSysmanDeviceImp->getRootDeviceEnvironment()))); + ASSERT_NE(nullptr, drm); + EXPECT_FALSE(drm->sysmanQueryEngineInfo()); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine_prelim.cpp b/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine_prelim.cpp new file mode 100644 index 0000000000..ad7d6a328b --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/engine/linux/test_zes_engine_prelim.cpp @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2022-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/libult/linux/drm_mock.h" + +#include "level_zero/sysman/test/unit_tests/sources/engine/linux/mock_engine_prelim.h" +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" +#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h" + +namespace L0 { +namespace ult { +constexpr uint32_t handleComponentCount = 13u; +constexpr uint32_t handleCountForMultiDeviceFixture = 7u; +class ZesEngineFixture : public SysmanDeviceFixture { + protected: + MockEngineNeoDrm *pDrm = nullptr; + std::unique_ptr pPmuInterface; + Drm *pOriginalDrm = nullptr; + L0::Sysman::PmuInterface *pOriginalPmuInterface = nullptr; + std::unique_ptr pSysfsAccess; + L0::Sysman::SysfsAccess *pSysfsAccessOriginal = nullptr; + std::unique_ptr pFsAccess; + L0::Sysman::FsAccess *pFsAccessOriginal = nullptr; + + L0::Sysman::SysmanDevice *device = nullptr; + + void SetUp() override { + SysmanDeviceFixture::SetUp(); + + pSysfsAccessOriginal = pLinuxSysmanImp->pSysfsAccess; + pSysfsAccess = std::make_unique(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pFsAccess = std::make_unique(); + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + + pDrm = new MockEngineNeoDrm(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterface->setDriverModel(std::unique_ptr(pDrm)); + + pPmuInterface = std::make_unique(pLinuxSysmanImp); + pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface; + pLinuxSysmanImp->pPmuInterface = pPmuInterface.get(); + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = true; + device = pSysmanDevice; + getEngineHandles(0); + } + + void TearDown() override { + pLinuxSysmanImp->pPmuInterface = pOriginalPmuInterface; + pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOriginal; + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + + SysmanDeviceFixture::TearDown(); + } + + std::vector getEngineHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(ZesEngineFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumEngineGroupsThenNonZeroCountIsReturnedAndVerifyCallSucceeds) { + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, handleComponentCount); + + uint32_t testcount = count + 1; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &testcount, NULL)); + EXPECT_EQ(testcount, count); + + count = 0; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, handleComponentCount); +} +TEST_F(ZesEngineFixture, GivenValidEngineHandlesWhenCallingZesEngineGetPropertiesThenVerifyCallSucceeds) { + zes_engine_properties_t properties; + auto handle = getEngineHandles(handleComponentCount); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[0], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_ALL, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[1], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_COMPUTE_ALL, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[2], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ALL, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[3], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_COPY_ALL, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[4], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_COMPUTE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[5], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[6], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[7], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[8], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[9], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[10], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_COPY_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[11], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENHANCEMENT_SINGLE, properties.type); + EXPECT_FALSE(properties.onSubdevice); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[12], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_ALL, properties.type); + EXPECT_FALSE(properties.onSubdevice); +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndIntegratedDeviceWhenCallingZesEngineGetActivityThenVerifyCallReturnsSuccess) { + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); + EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); + EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + } +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndDiscreteDeviceWhenCallingZesEngineGetActivityThenVerifyCallReturnsSuccess) { + + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = false; + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); + EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); + EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + } +} + +TEST_F(ZesEngineFixture, GivenTestDiscreteDevicesAndValidEngineHandleWhenCallingZesEngineGetActivityAndPMUGetEventTypeFailsThenVerifyEngineGetActivityReturnsFailure) { + + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = false; + pSysfsAccess->mockReadSymLinkFailure = true; + + auto pOsEngineTest1 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + + zes_engine_stats_t stats = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest1->getActivity(&stats)); + + pSysfsAccess->mockReadSymLinkSuccess = true; + pFsAccess->mockReadVal = true; + + auto pOsEngineTest2 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest2->getActivity(&stats)); + delete pOsEngineTest1; + delete pOsEngineTest2; +} + +TEST_F(ZesEngineFixture, GivenUnknownEngineTypeThengetEngineGroupFromTypeReturnsGroupAllEngineGroup) { + auto group = L0::Sysman::LinuxEngineImp::getGroupFromEngineType(ZES_ENGINE_GROUP_3D_SINGLE); + EXPECT_EQ(group, ZES_ENGINE_GROUP_ALL); +} + +TEST_F(ZesEngineFixture, GivenTestIntegratedDevicesAndValidEngineHandleWhenCallingZesEngineGetActivityAndPMUGetEventTypeFailsThenVerifyEngineGetActivityReturnsFailure) { + zes_engine_stats_t stats = {}; + + pFsAccess->mockReadVal = true; + + auto pOsEngineTest1 = L0::Sysman::OsEngine::create(pOsSysman, ZES_ENGINE_GROUP_RENDER_SINGLE, 0u, 0u, false); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsEngineTest1->getActivity(&stats)); + delete pOsEngineTest1; +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleWhenCallingZesEngineGetActivityAndPmuReadFailsThenVerifyEngineGetActivityReturnsFailure) { + + pPmuInterface->mockPmuRead = true; + + zes_engine_stats_t stats = {}; + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesEngineGetActivity(handle, &stats)); + } +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleWhenCallingZesEngineGetActivityAndperfEventOpenFailsThenVerifyEngineGetActivityReturnsFailure) { + + pPmuInterface->mockPerfEventOpenRead = true; + + MockEnginePmuInterfaceImp pPmuInterfaceImp(pLinuxSysmanImp); + EXPECT_EQ(-1, pPmuInterface->pmuInterfaceOpen(0, -1, 0)); +} + +TEST_F(ZesEngineFixture, GivenValidOsSysmanPointerWhenRetrievingEngineTypeAndInstancesAndIfEngineInfoQueryFailsThenErrorIsReturned) { + std::set>> engineGroupInstance; + + pDrm->mockReadSysmanQueryEngineInfo = true; + + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, L0::Sysman::OsEngine::getNumEngineTypeAndInstances(engineGroupInstance, pOsSysman)); +} + +TEST_F(ZesEngineFixture, GivenHandleQueryItemCalledWithInvalidEngineTypeThenzesDeviceEnumEngineGroupsSucceeds) { + + uint32_t count = 0; + uint32_t mockHandleCount = 13u; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, mockHandleCount); +} + +TEST_F(ZesEngineFixture, GivenHandleQueryItemCalledWhenPmuInterfaceOpenFailsThenzesDeviceEnumEngineGroupsSucceedsAndHandleCountIsZero) { + + pFsAccess->mockReadVal = true; + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(pOsSysman->getSubDeviceCount()); + uint32_t count = 0; + uint32_t mockHandleCount = 0u; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, mockHandleCount); +} + +TEST_F(ZesEngineFixture, GivenValidDrmObjectWhenCallingsysmanQueryEngineInfoMethodThenSuccessIsReturned) { + auto drm = std::make_unique(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + ASSERT_NE(nullptr, drm); + EXPECT_TRUE(drm->sysmanQueryEngineInfo()); + auto engineInfo = drm->getEngineInfo(); + ASSERT_NE(nullptr, engineInfo); +} + +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndHandleCountZeroWhenCallingReInitThenValidCountIsReturnedAndVerifyzesDeviceEnumEngineGroupsSucceeds) { + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, handleComponentCount); + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(pOsSysman->getSubDeviceCount()); + + count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, handleComponentCount); +} + +class ZesEngineMultiFixture : public SysmanMultiDeviceFixture { + protected: + std::unique_ptr pPmuInterface; + L0::Sysman::PmuInterface *pOriginalPmuInterface = nullptr; + std::unique_ptr pSysfsAccess; + L0::Sysman::SysfsAccess *pSysfsAccessOriginal = nullptr; + std::unique_ptr pFsAccess; + L0::Sysman::FsAccess *pFsAccessOriginal = nullptr; + L0::Sysman::SysmanDevice *device = nullptr; + + void SetUp() override { + SysmanMultiDeviceFixture::SetUp(); + pSysfsAccessOriginal = pLinuxSysmanImp->pSysfsAccess; + pSysfsAccess = std::make_unique(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pFsAccess = std::make_unique(); + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + + MockEngineNeoDrm *pDrm = new MockEngineNeoDrm(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterface->setDriverModel(std::unique_ptr(pDrm)); + + pPmuInterface = std::make_unique(pLinuxSysmanImp); + pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface; + pLinuxSysmanImp->pPmuInterface = pPmuInterface.get(); + + pDrm->mockReadSysmanQueryEngineInfoMultiDevice = true; + pSysfsAccess->mockReadSymLinkSuccess = true; + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = true; + device = pSysmanDevice; + getEngineHandles(0); + } + + void TearDown() override { + SysmanMultiDeviceFixture::TearDown(); + pLinuxSysmanImp->pPmuInterface = pOriginalPmuInterface; + pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOriginal; + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + } + + std::vector getEngineHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(ZesEngineMultiFixture, GivenComponentCountZeroWhenCallingzesDeviceEnumEngineGroupsThenNonZeroCountIsReturnedAndVerifyCallSucceeds) { + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, handleCountForMultiDeviceFixture); + + uint32_t testcount = count + 1; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &testcount, NULL)); + EXPECT_EQ(testcount, count); + + count = 0; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumEngineGroups(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, handleCountForMultiDeviceFixture); +} + +TEST_F(ZesEngineMultiFixture, GivenValidEngineHandlesWhenCallingZesEngineGetPropertiesThenVerifyCallSucceeds) { + zes_engine_properties_t properties; + auto handle = getEngineHandles(handleCountForMultiDeviceFixture); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[0], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_ALL, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[1], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_ALL, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 1u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[2], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ALL, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 1u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[3], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_SINGLE, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[4], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_DECODE_SINGLE, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 1u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[5], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_MEDIA_ENCODE_SINGLE, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 1u); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetProperties(handle[6], &properties)); + EXPECT_EQ(ZES_ENGINE_GROUP_RENDER_ALL, properties.type); + EXPECT_TRUE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); +} + +TEST_F(ZesEngineMultiFixture, GivenHandleQueryItemCalledWhenPmuInterfaceOpenFailsThenzesDeviceEnumEngineGroupsSucceedsAndHandleCountIsZero) { + + pFsAccess->mockReadVal = true; + + for (auto handle : pSysmanDeviceImp->pEngineHandleContext->handleList) { + delete handle; + } + + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(pOsSysman->getSubDeviceCount()); + uint32_t count = 0; + uint32_t mockHandleCount = 0u; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEnumEngineGroups(device->toHandle(), &count, NULL)); + EXPECT_EQ(count, mockHandleCount); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/tools/source/sysman/engine/engine.h b/level_zero/tools/source/sysman/engine/engine.h index f3d6b01730..c1a2866a80 100644 --- a/level_zero/tools/source/sysman/engine/engine.h +++ b/level_zero/tools/source/sysman/engine/engine.h @@ -6,16 +6,13 @@ */ #pragma once +#include "level_zero/api/sysman/zes_handles_struct.h" #include "level_zero/core/source/device/device.h" #include #include #include -struct _zes_engine_handle_t { - virtual ~_zes_engine_handle_t() = default; -}; - namespace L0 { using EngineInstanceSubDeviceId = std::pair; struct OsSysman;