From 2f0fcf4aee4469103d94dc39d87550c6f468d472 Mon Sep 17 00:00:00 2001 From: Daniel Enriquez Date: Tue, 3 Aug 2021 20:14:47 -0700 Subject: [PATCH] Sysman for Windows: Fix Free memory from get state. KMD no longer tracks allocation, move to use OS functions. Signed-off-by: Daniel Enriquez --- .../sysman/memory/windows/os_memory_imp.cpp | 72 ++++++++++++++++--- .../sysman/memory/windows/os_memory_imp.h | 25 ++++++- .../source/sysman/windows/kmd_sys_manager.h | 1 + 3 files changed, 88 insertions(+), 10 deletions(-) diff --git a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp index 581b4cdcea..e3766313af 100644 --- a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp +++ b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.cpp @@ -7,6 +7,35 @@ #include "sysman/memory/windows/os_memory_imp.h" +template +std::string intToHex(I w, size_t hexLength = sizeof(I) << 1) { + static const char *digits = "0123456789ABCDEF"; + std::string retString(hexLength, '0'); + constexpr uint32_t intSize = sizeof(uint32_t); + for (size_t i = 0, j = (hexLength - 1) * intSize; i < hexLength; ++i, j -= intSize) + retString[i] = digits[(w >> j) & 0x0f]; + return (std::string("0x") + retString); +} + +std::wstring toWString(std::string str) { + std::wstring wsTmp(str.begin(), str.end()); + return wsTmp; +} + +std::wstring constructCounterStr(std::wstring object, std::wstring counter, LUID luid, uint32_t index) { + std::wstring fstr = L"\\"; + fstr += object; + fstr += L"(luid_"; + fstr += toWString(intToHex((long)luid.HighPart)); + fstr += L"_"; + fstr += toWString(intToHex((unsigned long)luid.LowPart)); + fstr += L"_phys_"; + fstr += std::to_wstring(index); + fstr += L")\\"; + fstr += counter; + return fstr; +} + namespace L0 { bool WddmMemoryImp::isMemoryModuleSupported() { uint32_t value = 0; @@ -176,16 +205,24 @@ ze_result_t WddmMemoryImp::getState(zes_mem_state_t *pState) { memcpy_s(&valueLarge, sizeof(uint64_t), response.dataBuffer, sizeof(uint64_t)); pState->size = valueLarge; - request.requestId = KmdSysman::Requests::Memory::CurrentFreeMemorySize; - - status = pKmdSysManager->requestSingle(request, response); - - if (status != ZE_RESULT_SUCCESS) { - return status; + if (!pdhInitialized) { + if (pdhOpenQuery && pdhOpenQuery(NULL, NULL, &gpuQuery) == ERROR_SUCCESS) { + pdhInitialized = true; + } } - memcpy_s(&valueLarge, sizeof(uint64_t), response.dataBuffer, sizeof(uint64_t)); - pState->free = valueLarge; + if (!pdhCounterAdded && pdhAddEnglishCounterW && pKmdSysManager->GetWddmAccess()) { + std::wstring counterStr = constructCounterStr(L"GPU Adapter Memory", L"Dedicated Usage", pKmdSysManager->GetWddmAccess()->getAdapterLuid(), 0); + pdhCounterAdded = (pdhAddEnglishCounterW(gpuQuery, counterStr.c_str(), NULL, &dedicatedUsage) == ERROR_SUCCESS); + } + + if (pdhCounterAdded && pdhCollectQueryData && pdhGetFormattedCounterValue) { + PDH_FMT_COUNTERVALUE counterVal; + pdhCollectQueryData(gpuQuery); + pdhGetFormattedCounterValue(dedicatedUsage, PDH_FMT_LARGE, NULL, &counterVal); + valueLarge = counterVal.largeValue; + pState->free = pState->size - valueLarge; + } return ZE_RESULT_SUCCESS; } @@ -194,6 +231,25 @@ WddmMemoryImp::WddmMemoryImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_ WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); pDevice = pWddmSysmanImp->getDeviceHandle(); + + hGetProcPDH = LoadLibrary(L"C:\\Windows\\System32\\pdh.dll"); + + if (hGetProcPDH) { + pdhOpenQuery = reinterpret_cast(GetProcAddress(hGetProcPDH, "PdhOpenQueryW")); + pdhAddEnglishCounterW = reinterpret_cast(GetProcAddress(hGetProcPDH, "PdhAddEnglishCounterW")); + pdhCollectQueryData = reinterpret_cast(GetProcAddress(hGetProcPDH, "PdhCollectQueryData")); + pdhGetFormattedCounterValue = reinterpret_cast(GetProcAddress(hGetProcPDH, "PdhGetFormattedCounterValue")); + pdhCloseQuery = reinterpret_cast(GetProcAddress(hGetProcPDH, "PdhCloseQuery")); + } +} + +WddmMemoryImp::~WddmMemoryImp() { + if (pdhInitialized && pdhCloseQuery) { + pdhCloseQuery(gpuQuery); + } + if (hGetProcPDH) { + FreeLibrary(hGetProcPDH); + } } OsMemory *OsMemory::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { diff --git a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h index 3b90348bf6..7a498f1a87 100644 --- a/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h +++ b/level_zero/tools/source/sysman/memory/windows/os_memory_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,12 +7,21 @@ #pragma once #include "shared/source/helpers/non_copyable_or_moveable.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" #include "level_zero/tools/source/sysman/sysman_const.h" #include "sysman/memory/os_memory.h" #include "sysman/windows/os_sysman_imp.h" +#include + +typedef PDH_STATUS(__stdcall *fn_PdhOpenQueryW)(LPCWSTR szDataSource, DWORD_PTR dwUserData, PDH_HQUERY *phQuery); +typedef PDH_STATUS(__stdcall *fn_PdhAddEnglishCounterW)(PDH_HQUERY hQuery, LPCWSTR szFullCounterPath, DWORD_PTR dwUserData, PDH_HCOUNTER *phCounter); +typedef PDH_STATUS(__stdcall *fn_PdhCollectQueryData)(PDH_HQUERY hQuery); +typedef PDH_STATUS(__stdcall *fn_PdhGetFormattedCounterValue)(PDH_HCOUNTER hCounter, DWORD dwFormat, LPDWORD lpdwType, PPDH_FMT_COUNTERVALUE pValue); +typedef PDH_STATUS(__stdcall *fn_PdhCloseQuery)(PDH_HQUERY hQuery); + namespace L0 { class KmdSysManager; @@ -24,13 +33,25 @@ class WddmMemoryImp : public OsMemory, NEO::NonCopyableOrMovableClass { bool isMemoryModuleSupported() override; WddmMemoryImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); WddmMemoryImp() = default; - ~WddmMemoryImp() override = default; + ~WddmMemoryImp(); protected: KmdSysManager *pKmdSysManager = nullptr; Device *pDevice = nullptr; bool isSubdevice = false; uint32_t subdeviceId = 0; + + fn_PdhOpenQueryW pdhOpenQuery = nullptr; + fn_PdhAddEnglishCounterW pdhAddEnglishCounterW = nullptr; + fn_PdhCollectQueryData pdhCollectQueryData = nullptr; + fn_PdhGetFormattedCounterValue pdhGetFormattedCounterValue = nullptr; + fn_PdhCloseQuery pdhCloseQuery = nullptr; + + bool pdhInitialized = false; + bool pdhCounterAdded = false; + PDH_HQUERY gpuQuery = nullptr; + PDH_HCOUNTER dedicatedUsage = nullptr; + HINSTANCE hGetProcPDH = nullptr; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/windows/kmd_sys_manager.h b/level_zero/tools/source/sysman/windows/kmd_sys_manager.h index 0e755ab20b..dc60aba6d3 100644 --- a/level_zero/tools/source/sysman/windows/kmd_sys_manager.h +++ b/level_zero/tools/source/sysman/windows/kmd_sys_manager.h @@ -26,6 +26,7 @@ class KmdSysManager { MOCKABLE_VIRTUAL ze_result_t requestSingle(KmdSysman::RequestProperty &In, KmdSysman::ResponseProperty &Out); ze_result_t requestMultiple(std::vector &vIn, std::vector &vOut); + NEO::Wddm *GetWddmAccess() { return pWddmAccess; } private: MOCKABLE_VIRTUAL bool escape(uint32_t escapeOp, uint64_t pDataIn, uint32_t dataInSize, uint64_t pDataOut, uint32_t dataOutSize);