diff --git a/src/plugins/AMD.cpp b/src/plugins/AMD.cpp index b9609b6..3855c71 100644 --- a/src/plugins/AMD.cpp +++ b/src/plugins/AMD.cpp @@ -817,6 +817,47 @@ std::vector> getForcePerfLevel(AMDGPUData data) { return {}; } +std::vector> getCoreUtilization(AMDGPUData data) { + auto func = [=]() -> ReadResult { + uint util; + if (amdgpu_query_sensor_info( + data.devHandle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(util), &util) == 0) + return util; + return ReadError::UnknownError; + }; + + DynamicReadable dr{func, _("%")}; + + if (hasReadableValue(func())) { + return {DeviceNode{ + .name = _("Core Utilization"), + .interface = dr, + .hash = md5(data.pciId + "Core Utilization"), + }}; + } + return {}; +} + +std::vector> getMemoryUtilization(AMDGPUData data) { + auto func = [=]() -> ReadResult { + auto string = fileContents(data.hwmonPath + "/mem_busy_percent"); + if (!string.has_value()) + return ReadError::UnknownError; + return static_cast(std::stoi(*string)); + }; + + DynamicReadable dr{func, _("%")}; + + if (hasReadableValue(func())) { + return {DeviceNode{ + .name = _("Memory Utilization"), + .interface = dr, + .hash = md5(data.pciId + "Memory Utilization"), + }}; + } + return {}; +} + std::vector> getVoltFreqRoot(AMDGPUData data) { if (data.ppTableType.has_value() && (*data.ppTableType == Navi || *data.ppTableType == SMU13)) @@ -883,6 +924,15 @@ std::vector> getMemoryPStateRoot(AMDGPUData data) { }}; } +std::vector> getUtilizationsRoot(AMDGPUData data) { + // TODO: PCIe bandwidth utilization missing + return {DeviceNode{ + .name = _("Utilizations"), + .interface = std::nullopt, + .hash = md5(data.pciId + "Utilizations"), + }}; +} + std::vector> getGPUName(AMDGPUData data) { auto name = amdgpu_get_marketing_name(data.devHandle); if (name) { @@ -908,6 +958,10 @@ auto gpuTree = TreeConstructor{ {getPowerLimit, {}}, {getPowerUsage, {}} }}, + {getUtilizationsRoot, { + {getMemoryUtilization, {}}, + {getCoreUtilization, {}} + }}, {getPerformanceRoot, { {getClocksRoot, { {getMemoryClockRead, {}},