From bc719ad80e0812b50ec3900b2c9969fdfb93332d Mon Sep 17 00:00:00 2001 From: "Kulkarni, Ashwin Kumar" Date: Mon, 5 Jun 2023 07:40:07 +0000 Subject: [PATCH] feature(sysman): supports performance module for zesInit windows Related-To: LOCI-4205 Signed-off-by: Kulkarni, Ashwin Kumar --- .../windows/sysman_os_performance_imp.cpp | 83 ++++++++- .../windows/sysman_os_performance_imp.h | 6 + .../performance/windows/CMakeLists.txt | 14 ++ .../performance/windows/mock_performance.h | 88 +++++++++ .../windows/test_zes_performance.cpp | 167 ++++++++++++++++++ 5 files changed, 354 insertions(+), 4 deletions(-) create mode 100644 level_zero/sysman/test/unit_tests/sources/performance/windows/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/performance/windows/mock_performance.h create mode 100644 level_zero/sysman/test/unit_tests/sources/performance/windows/test_zes_performance.cpp diff --git a/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.cpp b/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.cpp index 1e736c5fb8..6c8c22d7e9 100644 --- a/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.cpp +++ b/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.cpp @@ -10,24 +10,99 @@ namespace L0 { namespace Sysman { +constexpr double maxPerformanceFactor = 100; +constexpr double halfOfMaxPerformanceFactor = 50; +constexpr double minPerformanceFactor = 0; +constexpr uint32_t mediaDynamicMode = 0; +constexpr uint32_t mediaOneToTwoMode = 128; +constexpr uint32_t mediaOneToOneMode = 256; + ze_result_t WddmPerformanceImp::osPerformanceGetConfig(double *pFactor) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + uint32_t value = 0; + request.paramInfo = static_cast(KmdSysman::ActivityDomainsType::ActivityDomainMedia); + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PerformanceComponent; + request.requestId = KmdSysman::Requests::Performance::Factor; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + if (value == mediaOneToOneMode) { + *pFactor = maxPerformanceFactor; + } else if (value == mediaOneToTwoMode) { + *pFactor = halfOfMaxPerformanceFactor; + } else if (value == mediaDynamicMode) { + *pFactor = minPerformanceFactor; + } else { + status = ZE_RESULT_ERROR_UNKNOWN; + } + return status; } ze_result_t WddmPerformanceImp::osPerformanceSetConfig(double pFactor) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + if (pFactor < minPerformanceFactor || pFactor > maxPerformanceFactor) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + uint32_t value = 0; + request.paramInfo = static_cast(KmdSysman::ActivityDomainsType::ActivityDomainMedia); + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PerformanceComponent; + request.requestId = KmdSysman::Requests::Performance::Factor; + request.dataSize = sizeof(uint32_t); + if (pFactor > halfOfMaxPerformanceFactor) { + value = mediaOneToOneMode; + } else if (pFactor > minPerformanceFactor) { + value = mediaOneToTwoMode; + } else { + value = mediaDynamicMode; + } + memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t)); + return pKmdSysManager->requestSingle(request, response); } ze_result_t WddmPerformanceImp::osPerformanceGetProperties(zes_perf_properties_t &properties) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + properties.onSubdevice = isSubdevice; + properties.subdeviceId = subDeviceId; + properties.engines = domain; + return ZE_RESULT_SUCCESS; } bool WddmPerformanceImp::isPerformanceSupported(void) { + if (domain == ZES_ENGINE_TYPE_FLAG_MEDIA) { + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + uint32_t value = 0; + + request.paramInfo = static_cast(KmdSysman::ActivityDomainsType::ActivityDomainMedia); + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PerformanceComponent; + request.requestId = KmdSysman::Requests::Performance::NumPerformanceDomains; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return false; + } + + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + return static_cast(value); + } return false; } WddmPerformanceImp::WddmPerformanceImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, - zes_engine_type_flag_t domain) {} + zes_engine_type_flag_t domain) : isSubdevice(onSubdevice), subDeviceId(subdeviceId), domain(domain) { + WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); +} OsPerformance *OsPerformance::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain) { diff --git a/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h b/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h index f2926e560b..f6493376cf 100644 --- a/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h +++ b/level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h @@ -22,6 +22,12 @@ class WddmPerformanceImp : public OsPerformance { WddmPerformanceImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain); ~WddmPerformanceImp() override = default; + + protected: + ze_bool_t isSubdevice = false; + uint32_t subDeviceId = 0; + KmdSysManager *pKmdSysManager = nullptr; + zes_engine_type_flag_t domain = ZES_ENGINE_TYPE_FLAG_OTHER; }; } // namespace Sysman diff --git a/level_zero/sysman/test/unit_tests/sources/performance/windows/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/performance/windows/CMakeLists.txt new file mode 100644 index 0000000000..3508b55635 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/performance/windows/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + target_sources(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_performance.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_performance.h + ) +endif() \ No newline at end of file diff --git a/level_zero/sysman/test/unit_tests/sources/performance/windows/mock_performance.h b/level_zero/sysman/test/unit_tests/sources/performance/windows/mock_performance.h new file mode 100644 index 0000000000..b27cbf191a --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/performance/windows/mock_performance.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h" + +namespace L0 { +namespace ult { + +struct PerformanceKmdSysManager : public MockKmdSysManager { + + uint32_t mockNumberOfDomains = 1; + uint32_t mockPerformanceFactor = 0; + void getPerformanceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { + uint8_t *pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + KmdSysman::ActivityDomainsType domain = static_cast(pRequest->inCommandParam); + + if (domain != KmdSysman::ActivityDomainsType::ActivityDomainMedia) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Performance::NumPerformanceDomains: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockNumberOfDomains; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Performance::Factor: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPerformanceFactor; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + void setPerformanceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { + uint8_t *pBuffer = reinterpret_cast(pRequest); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + KmdSysman::ActivityDomainsType domain = static_cast(pRequest->inCommandParam); + + if (domain != KmdSysman::ActivityDomainsType::ActivityDomainMedia) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Performance::Factor: { + uint32_t *pValue = reinterpret_cast(pBuffer); + mockPerformanceFactor = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + // Mock() = default; + //~Mock() override = default; +}; + +class PublicWddmPerformanceImp : public L0::Sysman::WddmPerformanceImp { + public: + PublicWddmPerformanceImp(L0::Sysman::OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain) : WddmPerformanceImp(pOsSysman, onSubdevice, subdeviceId, domain) {} + using WddmPerformanceImp::domain; + using WddmPerformanceImp::pKmdSysManager; +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/performance/windows/test_zes_performance.cpp b/level_zero/sysman/test/unit_tests/sources/performance/windows/test_zes_performance.cpp new file mode 100644 index 0000000000..f01284b7a4 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/performance/windows/test_zes_performance.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/performance/windows/sysman_os_performance_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/performance/windows/mock_performance.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h" + +namespace L0 { +namespace ult { + +constexpr uint32_t mockHandleCount = 1u; +constexpr double maxPerformanceFactor = 100; +constexpr double halfOfMaxPerformanceFactor = 50; +constexpr double minPerformanceFactor = 0; + +class SysmanDevicePerformanceFixture : public SysmanDeviceFixture { + protected: + std::unique_ptr pKmdSysManager; + L0::Sysman::KmdSysManager *pOriginalKmdSysManager = nullptr; + void SetUp() override { + SysmanDeviceFixture::SetUp(); + pKmdSysManager.reset(new PerformanceKmdSysManager); + + pKmdSysManager->allowSetCalls = true; + + pOriginalKmdSysManager = pWddmSysmanImp->pKmdSysManager; + pWddmSysmanImp->pKmdSysManager = pKmdSysManager.get(); + + pSysmanDeviceImp->pPerformanceHandleContext->handleList.clear(); + } + + void TearDown() override { + pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager; + SysmanDeviceFixture::TearDown(); + } + + std::vector getPerfHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(SysmanDevicePerformanceFixture, GivenValidSysmanHandleWhenRetrievingPerfThenValidHandlesReturned) { + uint32_t count = 0; + ze_result_t result = zesDeviceEnumPerformanceFactorDomains(pSysmanDevice->toHandle(), &count, NULL); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(count, mockHandleCount); + + uint32_t testcount = count + 1; + result = zesDeviceEnumPerformanceFactorDomains(pSysmanDevice->toHandle(), &testcount, NULL); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(testcount, mockHandleCount); + + count = 0; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, mockHandleCount); +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidSysmanHandleWhenRetrievingPerfAndRequestSingleFailsThenFailuresAreReturned) { + pKmdSysManager->mockRequestSingle = true; + pKmdSysManager->mockRequestSingleResult = ZE_RESULT_ERROR_UNKNOWN; + uint32_t count = 0; + ze_result_t result = zesDeviceEnumPerformanceFactorDomains(pSysmanDevice->toHandle(), &count, NULL); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(count, 0u); +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandleWhenGettingPerformancePropertiesThenValidPropertiesReturned) { + auto handles = getPerfHandles(mockHandleCount); + for (const auto &handle : handles) { + zes_perf_properties_t properties = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handle, &properties)); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.engines, ZES_ENGINE_TYPE_FLAG_MEDIA); + EXPECT_EQ(properties.subdeviceId, 0u); + } +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandleWhenSettingMediaConfigAndGettingMediaConfigThenSuccessIsReturned) { + pKmdSysManager->allowSetCalls = true; + auto handles = getPerfHandles(mockHandleCount); + for (const auto &handle : handles) { + zes_perf_properties_t properties = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handle, &properties)); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + double setFactor = 49; + double getFactor = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), halfOfMaxPerformanceFactor); + + setFactor = 50; + getFactor = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), halfOfMaxPerformanceFactor); + + setFactor = 60; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), maxPerformanceFactor); + + setFactor = 100; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), maxPerformanceFactor); + + setFactor = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), minPerformanceFactor); + } + } +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandlesWhenRetrievingPerformanceFactorAndKmdReturnsInvalidValueThenUnknownErrorIsReturned) { + pKmdSysManager->mockPerformanceFactor = 512; + auto handles = getPerfHandles(mockHandleCount); + for (const auto &handle : handles) { + double factor = 0; + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesPerformanceFactorGetConfig(handle, &factor)); + } +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandleWhenRetrievingPerformanceFactorAndOsPerformanceGetConfigFailsThenFailureIsReturned) { + pKmdSysManager->mockRequestSingle = true; + pKmdSysManager->mockRequestSingleResult = ZE_RESULT_ERROR_UNKNOWN; + PublicWddmPerformanceImp *pWddmPerformanceImp = new PublicWddmPerformanceImp(pOsSysman, 0, 0u, ZES_ENGINE_TYPE_FLAG_MEDIA); + double pFactor = 0; + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, pWddmPerformanceImp->osPerformanceGetConfig(&pFactor)); + delete pWddmPerformanceImp; +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandleWhenRetrievingPerformanceFactorAndOsPerformanceSetConfigFailsThenFailureIsReturned) { + pKmdSysManager->allowSetCalls = true; + pKmdSysManager->mockRequestSingle = true; + pKmdSysManager->mockRequestSingleResult = ZE_RESULT_ERROR_UNKNOWN; + PublicWddmPerformanceImp *pWddmPerformanceImp = new PublicWddmPerformanceImp(pOsSysman, 0, 0u, ZES_ENGINE_TYPE_FLAG_MEDIA); + double pFactor = halfOfMaxPerformanceFactor; + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, pWddmPerformanceImp->osPerformanceSetConfig(pFactor)); + delete pWddmPerformanceImp; +} + +TEST_F(SysmanDevicePerformanceFixture, GivenValidPerfHandleWhenSettingPerformanceFactorWithInvalidValuesThenInvalidArgumentErrorIsReturned) { + pKmdSysManager->allowSetCalls = true; + auto handles = getPerfHandles(mockHandleCount); + for (const auto &handle : handles) { + zes_perf_properties_t properties = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handle, &properties)); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + double setFactor = -1; + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zesPerformanceFactorSetConfig(handle, setFactor)); + + setFactor = 110; + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zesPerformanceFactorSetConfig(handle, setFactor)); + } + } +} + +} // namespace ult +} // namespace L0 \ No newline at end of file