diff --git a/IntelPresentMon/AppCef/CefNano.args.json b/IntelPresentMon/AppCef/CefNano.args.json index 0b8a72610..5bff3e27d 100644 --- a/IntelPresentMon/AppCef/CefNano.args.json +++ b/IntelPresentMon/AppCef/CefNano.args.json @@ -88,6 +88,10 @@ "Id": "fc633c46-6b09-43e6-9c02-3e4817ef382e", "Command": "--p2c-debug-wait-render" }, + { + "Id": "f556bf27-cb7e-4a17-a7cb-3c0400aeb7d1", + "Command": "--p2c-debug-wait-client" + }, { "Id": "92d25458-0b38-4e99-a582-49f0c90979c2", "Command": "--help" diff --git a/IntelPresentMon/CommonUtilities/ref/StaticReflection.h b/IntelPresentMon/CommonUtilities/ref/StaticReflection.h index 54b8b6445..7fd4a82f3 100644 --- a/IntelPresentMon/CommonUtilities/ref/StaticReflection.h +++ b/IntelPresentMon/CommonUtilities/ref/StaticReflection.h @@ -6,6 +6,7 @@ #include #include "WrapReflect.h" #include "../Meta.h" +#include namespace pmon::util::ref @@ -36,7 +37,7 @@ namespace pmon::util::ref oss << "{unknown}"; } else if constexpr (std::is_enum_v) { - oss << reflect::enum_name(s); + oss << reflect::type_name() << "::" << reflect::enum_name(s); } else if constexpr (std::is_class_v) { oss << "struct " << reflect::type_name(s) << " { "; @@ -64,4 +65,51 @@ namespace pmon::util::ref DumpStaticImpl_(s, oss); return oss.str(); } + + template + std::string DumpEnumBitset(const std::bitset& set) + { + std::ostringstream oss; + oss << "| "; + for (size_t n = 0; n < N; n++) { + if (!set.test(n)) { + continue; + } + const auto name = reflect::enum_name(E(n)); + if (!name.length()) { + continue; + } + oss << name << ", "; + } + oss << "|"; + return oss.str(); + } + + template + std::string DumpEnumFlagSet(uint64_t bits) + { + // simple hacky impl assumes 32-bit ints, logically unsigned for flags + // unless underlying type is 8-bytes, then assume 64-bit + size_t nBits; + if constexpr (sizeof(std::underlying_type_t) == 8) { + nBits = 64; + } + else { + nBits = 32; + } + std::ostringstream oss; + oss << "| "; + // loop over n-bits, shifting a 1-hot bit value to test all positions + for (size_t n = 0, b = 1; n < nBits; n++, b<<1) { + if (!(bits & b)) { + continue; + } + const auto name = reflect::enum_name(E(b)); + if (!name.length()) { + continue; + } + oss << name << ", "; + } + oss << "|"; + } } \ No newline at end of file diff --git a/IntelPresentMon/CommonUtilities/ref/gen/GeneratedReflection.h b/IntelPresentMon/CommonUtilities/ref/gen/GeneratedReflection.h index a5849ebb7..3dbb2f7a6 100644 --- a/IntelPresentMon/CommonUtilities/ref/gen/GeneratedReflection.h +++ b/IntelPresentMon/CommonUtilities/ref/gen/GeneratedReflection.h @@ -1364,6 +1364,43 @@ namespace pmon::util::ref::gen << " }"; return oss.str(); }; + dumpers[typeid(_ctl_led_properties_t)] = [](const void* pStruct) { + const auto& s = *static_cast(pStruct); + std::ostringstream oss; + oss << std::boolalpha << "struct _ctl_led_properties_t {" + << " .Size = " << s.Size + << " .Version = " << (int)s.Version + << " .canControl = " << s.canControl + << " .isI2C = " << s.isI2C + << " .isPWM = " << s.isPWM + << " .haveRGB = " << s.haveRGB + << " }"; + return oss.str(); + }; + dumpers[typeid(_ctl_led_color_t)] = [](const void* pStruct) { + const auto& s = *static_cast(pStruct); + std::ostringstream oss; + oss << std::boolalpha << "struct _ctl_led_color_t {" + << " .Size = " << s.Size + << " .Version = " << (int)s.Version + << " .red = " << s.red + << " .green = " << s.green + << " .blue = " << s.blue + << " }"; + return oss.str(); + }; + dumpers[typeid(_ctl_led_state_t)] = [](const void* pStruct) { + const auto& s = *static_cast(pStruct); + std::ostringstream oss; + oss << std::boolalpha << "struct _ctl_led_state_t {" + << " .Size = " << s.Size + << " .Version = " << (int)s.Version + << " .isOn = " << s.isOn + << " .pwm = " << s.pwm + << " .color = " << DumpGenerated(s.color) + << " }"; + return oss.str(); + }; dumpers[typeid(_ctl_video_processing_super_resolution_info_t)] = [](const void* pStruct) { const auto& s = *static_cast(pStruct); std::ostringstream oss; @@ -1689,6 +1726,15 @@ namespace pmon::util::ref::gen << " .totalCardEnergyCounter = " << DumpGenerated(s.totalCardEnergyCounter) << " .psu = " << DumpArray_(s.psu) << " .fanSpeed = " << DumpArray_(s.fanSpeed) + << " .gpuVrTemp = " << DumpGenerated(s.gpuVrTemp) + << " .vramVrTemp = " << DumpGenerated(s.vramVrTemp) + << " .saVrTemp = " << DumpGenerated(s.saVrTemp) + << " .gpuEffectiveClock = " << DumpGenerated(s.gpuEffectiveClock) + << " .gpuOverVoltagePercent = " << DumpGenerated(s.gpuOverVoltagePercent) + << " .gpuPowerPercent = " << DumpGenerated(s.gpuPowerPercent) + << " .gpuTemperaturePercent = " << DumpGenerated(s.gpuTemperaturePercent) + << " .vramReadBandwidth = " << DumpGenerated(s.vramReadBandwidth) + << " .vramWriteBandwidth = " << DumpGenerated(s.vramWriteBandwidth) << " }"; return oss.str(); }; @@ -2041,6 +2087,7 @@ namespace pmon::util::ref::gen case _ctl_units_t::CTL_UNITS_PERCENT: return "CTL_UNITS_PERCENT"s; case _ctl_units_t::CTL_UNITS_MEM_SPEED_GBPS: return "CTL_UNITS_MEM_SPEED_GBPS"s; case _ctl_units_t::CTL_UNITS_VOLTAGE_MILLIVOLTS: return "CTL_UNITS_VOLTAGE_MILLIVOLTS"s; + case _ctl_units_t::CTL_UNITS_BANDWIDTH_MBPS: return "CTL_UNITS_BANDWIDTH_MBPS"s; case _ctl_units_t::CTL_UNITS_UNKNOWN: return "CTL_UNITS_UNKNOWN"s; case _ctl_units_t::CTL_UNITS_MAX: return "CTL_UNITS_MAX"s; default: return "{ unknown }"s; @@ -2602,6 +2649,7 @@ namespace pmon::util::ref::gen dumpers[typeid(_ctl_3d_feature_misc_flag_t)] = [](const void* pEnum) { const auto& e = *static_cast(pEnum); switch (e) { + case _ctl_3d_feature_misc_flag_t::CTL_3D_FEATURE_MISC_FLAG_DX9: return "CTL_3D_FEATURE_MISC_FLAG_DX9"s; case _ctl_3d_feature_misc_flag_t::CTL_3D_FEATURE_MISC_FLAG_DX11: return "CTL_3D_FEATURE_MISC_FLAG_DX11"s; case _ctl_3d_feature_misc_flag_t::CTL_3D_FEATURE_MISC_FLAG_DX12: return "CTL_3D_FEATURE_MISC_FLAG_DX12"s; case _ctl_3d_feature_misc_flag_t::CTL_3D_FEATURE_MISC_FLAG_VULKAN: return "CTL_3D_FEATURE_MISC_FLAG_VULKAN"s; diff --git a/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.cpp b/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.cpp index 4d4d74fd5..5a4d33e3a 100644 --- a/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.cpp +++ b/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.cpp @@ -6,12 +6,68 @@ #include "../CommonUtilities/ref/GeneratedReflection.h" #include "../CommonUtilities/ref/StaticReflection.h" #include +#include using namespace pmon; using namespace util; +namespace vi = std::views; namespace pwr::intel { + namespace { + GpuTelemetryCapBits GetFanSpeedTelemetryCapBit_( + uint32_t fan_index) { + switch (fan_index) { + case 0: + return GpuTelemetryCapBits::fan_speed_0; + case 1: + return GpuTelemetryCapBits::fan_speed_1; + case 2: + return GpuTelemetryCapBits::fan_speed_2; + case 3: + return GpuTelemetryCapBits::fan_speed_3; + case 4: + return GpuTelemetryCapBits::fan_speed_4; + default: + throw std::runtime_error{ "Invalid fan speed index" }; + } + } + GpuTelemetryCapBits GetPsuTelemetryCapBit_( + uint32_t psu_index) { + switch (psu_index) { + case 0: + return GpuTelemetryCapBits::psu_info_0; + case 1: + return GpuTelemetryCapBits::psu_info_1; + case 2: + return GpuTelemetryCapBits::psu_info_2; + case 3: + return GpuTelemetryCapBits::psu_info_3; + case 4: + return GpuTelemetryCapBits::psu_info_4; + default: + throw std::runtime_error{ "Invalid PSU index" }; + } + } + GpuTelemetryCapBits GetMaxFanSpeedTelemetryCapBit_( + uint32_t index) { + switch (index) { + case 0: + return GpuTelemetryCapBits::max_fan_speed_0; + case 1: + return GpuTelemetryCapBits::max_fan_speed_1; + case 2: + return GpuTelemetryCapBits::max_fan_speed_2; + case 3: + return GpuTelemetryCapBits::max_fan_speed_3; + case 4: + return GpuTelemetryCapBits::max_fan_speed_4; + default: + throw std::runtime_error{ "Invalid max fan speed index" }; + } + } + } + // public interface functions IntelPowerTelemetryAdapter::IntelPowerTelemetryAdapter(ctl_device_adapter_handle_t handle) @@ -60,6 +116,38 @@ namespace pwr::intel else { pmlog_error("ctlEnumPowerDomains failed to get count").code(result).pmwatch(GetName()); } + + // enumerate fans + uint32_t fanCount = 0; + if (auto res = ctlEnumFans(deviceHandle, &fanCount, nullptr); res == CTL_RESULT_SUCCESS) { + if (fanCount > 0) { + std::vector fanHandles(fanCount); + if (auto res = ctlEnumFans(deviceHandle, &fanCount, fanHandles.data()); res == CTL_RESULT_SUCCESS) { + for (auto&&[iFan, hFan] : vi::enumerate(fanHandles)) { + if (hFan) { + ctl_fan_properties_t props{ .Size = sizeof(ctl_fan_properties_t) }; + if (auto res = ctlFanGetProperties(hFan, &props); res != CTL_RESULT_SUCCESS) { + pmlog_error(std::format("failed to get properties for fan #{}", iFan)).code(res); + maxFanSpeedsRpm_.push_back(0); + } + pmlog_verb(v::gpu)("Got fan properties").pmwatch(GetName()).pmwatch(iFan) + .pmwatch(ref::DumpGenerated(props)); + maxFanSpeedsRpm_.push_back(props.maxRPM); + } + else { + pmlog_warn("null handle received from ctlEnumFans"); + maxFanSpeedsRpm_.push_back(0); + } + } + } + else { + pmlog_error("failed getting fan handles").code(res); + } + } + } + else { + pmlog_error("failed getting fan count").code(res); + } } bool IntelPowerTelemetryAdapter::Sample() noexcept @@ -127,6 +215,7 @@ namespace pwr::intel IGCL_ERR(result); } pmlog_verb(v::gpu)("get memory state").pmwatch(GetName()).pmwatch(ref::DumpGenerated(memory_state)); + if (const auto result = ctlMemoryGetBandwidth(memoryModules[0], &memory_bandwidth); result != CTL_RESULT_SUCCESS) { success = false; @@ -447,6 +536,15 @@ namespace pwr::intel return result; } + result = GetPowerTelemetryItemUsage( + currentSample.totalCardEnergyCounter, + previousSample->totalCardEnergyCounter, + pm_gpu_power_telemetry_info.gpu_card_power_w, + GpuTelemetryCapBits::gpu_card_power); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + result = GetPowerTelemetryItemUsagePercent( currentSample.globalActivityCounter, previousSample->globalActivityCounter, @@ -498,6 +596,57 @@ namespace pwr::intel SetTelemetryCapBit(GpuTelemetryCapBits::gpu_current_limited); } + // these metrics only available with V1 struct + if constexpr (std::same_as) { + result = GetInstantaneousPowerTelemetryItem( + currentSample.gpuEffectiveClock, + pm_gpu_power_telemetry_info.gpu_effective_frequency_mhz, + GpuTelemetryCapBits::gpu_effective_frequency); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + + result = GetInstantaneousPowerTelemetryItem( + currentSample.gpuVrTemp, + pm_gpu_power_telemetry_info.gpu_voltage_regulator_temperature_c, + GpuTelemetryCapBits::gpu_voltage_regulator_temperature); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + + result = GetInstantaneousPowerTelemetryItem( + currentSample.vramCurrentEffectiveFrequency, + pm_gpu_power_telemetry_info.gpu_mem_effective_bandwidth_gbps, + GpuTelemetryCapBits::gpu_mem_effective_bandwidth); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + + result = GetInstantaneousPowerTelemetryItem( + currentSample.gpuOverVoltagePercent, + pm_gpu_power_telemetry_info.gpu_overvoltage_percent, + GpuTelemetryCapBits::gpu_overvoltage_percent); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + + result = GetInstantaneousPowerTelemetryItem( + currentSample.gpuTemperaturePercent, + pm_gpu_power_telemetry_info.gpu_temperature_percent, + GpuTelemetryCapBits::gpu_temperature_percent); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + + result = GetInstantaneousPowerTelemetryItem( + currentSample.gpuPowerPercent, + pm_gpu_power_telemetry_info.gpu_power_percent, + GpuTelemetryCapBits::gpu_power_percent); + if (result != CTL_RESULT_SUCCESS) { + return result; + } + } + return result; } @@ -631,15 +780,18 @@ namespace pwr::intel ctl_result_t result = CTL_RESULT_SUCCESS; for (uint32_t i = 0; i < CTL_FAN_COUNT; i++) { - GpuTelemetryCapBits fan_telemetry_bit; try { - fan_telemetry_bit = GetFlagTelemetryCapBit(i); + const auto fanSpeedCapBit = GetFanSpeedTelemetryCapBit_(i); result = GetInstantaneousPowerTelemetryItem( currentSample.fanSpeed[i], pm_gpu_power_telemetry_info.fan_speed_rpm[i], - fan_telemetry_bit); + fanSpeedCapBit); if (result != CTL_RESULT_SUCCESS) { - break; + break; + } + if (HasTelemetryCapBit(fanSpeedCapBit) && maxFanSpeedsRpm_[i] > 0) { + SetTelemetryCapBit(GetMaxFanSpeedTelemetryCapBit_(i)); + pm_gpu_power_telemetry_info.max_fan_speed_rpm[i] = maxFanSpeedsRpm_[i]; } } catch (...) { result = CTL_RESULT_ERROR_INVALID_ARGUMENT; @@ -665,7 +817,7 @@ namespace pwr::intel if (currentSample.psu[i].bSupported) { GpuTelemetryCapBits psu_telemetry_bit; try { - psu_telemetry_bit = GetPsuTelemetryCapBit(i); + psu_telemetry_bit = GetPsuTelemetryCapBit_(i); pm_gpu_power_telemetry_info.psu[i].psu_type = PresentMonPsuType(currentSample.psu[i].psuType); result = GetInstantaneousPowerTelemetryItem( @@ -831,40 +983,4 @@ namespace pwr::intel history.Push(info); } - GpuTelemetryCapBits IntelPowerTelemetryAdapter::GetFlagTelemetryCapBit( - uint32_t fan_index) { - switch (fan_index) { - case 0: - return GpuTelemetryCapBits::fan_speed_0; - case 1: - return GpuTelemetryCapBits::fan_speed_1; - case 2: - return GpuTelemetryCapBits::fan_speed_2; - case 3: - return GpuTelemetryCapBits::fan_speed_3; - case 4: - return GpuTelemetryCapBits::fan_speed_4; - default: - throw std::runtime_error{"Invalid fan index"}; - } - } - - GpuTelemetryCapBits IntelPowerTelemetryAdapter::GetPsuTelemetryCapBit( - uint32_t psu_index) { - switch (psu_index) { - case 0: - return GpuTelemetryCapBits::psu_info_0; - case 1: - return GpuTelemetryCapBits::psu_info_1; - case 2: - return GpuTelemetryCapBits::psu_info_2; - case 3: - return GpuTelemetryCapBits::psu_info_3; - case 4: - return GpuTelemetryCapBits::psu_info_4; - default: - throw std::runtime_error{"Invalid PSU index"}; - } - } - } \ No newline at end of file diff --git a/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.h b/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.h index 50940dbd9..e84afde56 100644 --- a/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.h +++ b/IntelPresentMon/ControlLib/IntelPowerTelemetryAdapter.h @@ -90,8 +90,6 @@ namespace pwr::intel const ctl_oc_telemetry_item_t& previous_telemetry_item, double& pm_telemetry_value, GpuTelemetryCapBits telemetry_cap_bit); - GpuTelemetryCapBits GetFlagTelemetryCapBit(uint32_t fan_index); - GpuTelemetryCapBits GetPsuTelemetryCapBit(uint32_t psu_index); // data ctl_device_adapter_handle_t deviceHandle = nullptr; LUID deviceId; // pointed to by a device_adapter_properties member, written to by igcl api @@ -115,5 +113,7 @@ namespace pwr::intel // we have special handling for GPU current perf limitation on Alchemist // workaround for lack of discoverablity of perf limitation availability bool isAlchemist = false; + // populated on init, used to calculate fan % + std::vector maxFanSpeedsRpm_; }; } \ No newline at end of file diff --git a/IntelPresentMon/ControlLib/NvidiaPowerTelemetryAdapter.cpp b/IntelPresentMon/ControlLib/NvidiaPowerTelemetryAdapter.cpp index 3ff3c8a31..a9b4c0826 100644 --- a/IntelPresentMon/ControlLib/NvidiaPowerTelemetryAdapter.cpp +++ b/IntelPresentMon/ControlLib/NvidiaPowerTelemetryAdapter.cpp @@ -188,10 +188,8 @@ namespace pwr::nv // TODO: consider logging failure (lower logging level perhaps) } } - } - // insert telemetry into history std::lock_guard lock{ historyMutex }; history.Push(info); diff --git a/IntelPresentMon/ControlLib/PowerTelemetryAdapter.cpp b/IntelPresentMon/ControlLib/PowerTelemetryAdapter.cpp index f789ce363..a305a9283 100644 --- a/IntelPresentMon/ControlLib/PowerTelemetryAdapter.cpp +++ b/IntelPresentMon/ControlLib/PowerTelemetryAdapter.cpp @@ -1,21 +1,35 @@ #include "PowerTelemetryAdapter.h" #include "Logging.h" +#include "../CommonUtilities/ref/WrapReflect.h" +#include "../CommonUtilities/ref/StaticReflection.h" #include namespace pwr { + using namespace std::literals; + using namespace pmon::util; + void PowerTelemetryAdapter::SetTelemetryCapBit(GpuTelemetryCapBits telemetryCapBit) noexcept { + if constexpr (v::gpu) { + if (!gpuTelemetryCapBits_.test(static_cast(telemetryCapBit))) { + pmlog_verb(v::gpu)("Telemetry cap bit being set: "s + std::string(reflect::enum_name(telemetryCapBit))) + .pmwatch(GetName()); + } + } gpuTelemetryCapBits_.set(static_cast(telemetryCapBit)); } PowerTelemetryAdapter::SetTelemetryCapBitset PowerTelemetryAdapter::GetPowerTelemetryCapBits() { + pmlog_verb(v::gpu)("Telemetry cap bits being retrieved").pmwatch(GetName()) + .pmwatch(ref::DumpEnumBitset(gpuTelemetryCapBits_)); return gpuTelemetryCapBits_; } bool PowerTelemetryAdapter::HasTelemetryCapBit(GpuTelemetryCapBits bit) const { - pmlog_verb(v::gpu)("Telemetry cap bits being retrieved").pmwatch(GetName()).pmwatch(gpuTelemetryCapBits_.to_string()); + pmlog_verb(v::gpu)("Telemetry cap bit being retrieved: "s + std::string(reflect::enum_name(bit))) + .pmwatch(GetName()).pmwatch(gpuTelemetryCapBits_.test(size_t(bit))); return gpuTelemetryCapBits_.test(size_t(bit)); } } \ No newline at end of file diff --git a/IntelPresentMon/ControlLib/PresentMonPowerTelemetry.h b/IntelPresentMon/ControlLib/PresentMonPowerTelemetry.h index 31b4c9880..cceb1fc66 100644 --- a/IntelPresentMon/ControlLib/PresentMonPowerTelemetry.h +++ b/IntelPresentMon/ControlLib/PresentMonPowerTelemetry.h @@ -32,6 +32,13 @@ struct PresentMonPowerTelemetryInfo { double gpu_utilization; double gpu_render_compute_utilization; double gpu_media_utilization; + double gpu_effective_frequency_mhz; + double gpu_voltage_regulator_temperature_c; + double gpu_mem_effective_bandwidth_gbps; + double gpu_overvoltage_percent; + double gpu_temperature_percent; + double gpu_power_percent; + double gpu_card_power_w; double vram_power_w; double vram_voltage_v; @@ -40,6 +47,7 @@ struct PresentMonPowerTelemetryInfo { double vram_temperature_c; std::array fan_speed_rpm; + std::array max_fan_speed_rpm; std::array psu; // GPU memory state @@ -66,46 +74,58 @@ struct PresentMonPowerTelemetryInfo { }; enum class GpuTelemetryCapBits { - time_stamp, - gpu_power, - gpu_sustained_power_limit, - gpu_voltage, - gpu_frequency, - gpu_temperature, - gpu_utilization, - gpu_render_compute_utilization, - gpu_media_utilization, - vram_power, - vram_voltage, - vram_frequency, - vram_effective_frequency, - vram_temperature, - fan_speed_0, - fan_speed_1, - fan_speed_2, - fan_speed_3, - fan_speed_4, - psu_info_0, - psu_info_1, - psu_info_2, - psu_info_3, - psu_info_4, - gpu_mem_size, - gpu_mem_used, - gpu_mem_max_bandwidth, - gpu_mem_write_bandwidth, - gpu_mem_read_bandwidth, - gpu_power_limited, - gpu_temperature_limited, - gpu_current_limited, - gpu_voltage_limited, - gpu_utilization_limited, - vram_power_limited, - vram_temperature_limited, - vram_current_limited, - vram_voltage_limited, - vram_utilization_limited, - gpu_telemetry_count + time_stamp, + gpu_power, + gpu_sustained_power_limit, + gpu_voltage, + gpu_frequency, + gpu_temperature, + gpu_utilization, + gpu_render_compute_utilization, + gpu_media_utilization, + vram_power, + vram_voltage, + vram_frequency, + vram_effective_frequency, + vram_temperature, + fan_speed_0, + fan_speed_1, + fan_speed_2, + fan_speed_3, + fan_speed_4, + psu_info_0, + psu_info_1, + psu_info_2, + psu_info_3, + psu_info_4, + gpu_mem_size, + gpu_mem_used, + gpu_mem_max_bandwidth, + gpu_mem_write_bandwidth, + gpu_mem_read_bandwidth, + gpu_power_limited, + gpu_temperature_limited, + gpu_current_limited, + gpu_voltage_limited, + gpu_utilization_limited, + vram_power_limited, + vram_temperature_limited, + vram_current_limited, + vram_voltage_limited, + vram_utilization_limited, + gpu_effective_frequency, + gpu_voltage_regulator_temperature, + gpu_mem_effective_bandwidth, + gpu_overvoltage_percent, + gpu_temperature_percent, + gpu_power_percent, + max_fan_speed_0, + max_fan_speed_1, + max_fan_speed_2, + max_fan_speed_3, + max_fan_speed_4, + gpu_card_power, + gpu_telemetry_count, }; using GpuTelemetryBitset = std::bitset(GpuTelemetryCapBits::gpu_telemetry_count)>; \ No newline at end of file diff --git a/IntelPresentMon/ControlLib/cApiWrapper.cpp b/IntelPresentMon/ControlLib/cApiWrapper.cpp index c881441ac..9723b25ec 100644 --- a/IntelPresentMon/ControlLib/cApiWrapper.cpp +++ b/IntelPresentMon/ControlLib/cApiWrapper.cpp @@ -3261,6 +3261,187 @@ ctlFrequencyGetThrottleTime( } +/** +* @brief Get handle of Leds +* +* @details +* - The application may call this function from simultaneous threads. +* - The implementation of this function should be lock-free. +* +* @returns +* - CTL_RESULT_SUCCESS +* - CTL_RESULT_ERROR_UNINITIALIZED +* - CTL_RESULT_ERROR_DEVICE_LOST +* - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +* + `nullptr == hDAhandle` +* - CTL_RESULT_ERROR_INVALID_NULL_POINTER +* + `nullptr == pCount` +*/ +ctl_result_t CTL_APICALL +ctlEnumLeds( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< If count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< If count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_led_handle_t* phLed ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< If count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ) +{ + ctl_result_t result = CTL_RESULT_ERROR_NOT_INITIALIZED; + + + HINSTANCE hinstLibPtr = GetLoaderHandle(); + + if (NULL != hinstLibPtr) + { + ctl_pfnEnumLeds_t pfnEnumLeds = (ctl_pfnEnumLeds_t)GetProcAddress(hinstLibPtr, "ctlEnumLeds"); + if (pfnEnumLeds) + { + result = pfnEnumLeds(hDAhandle, pCount, phLed); + } + } + + return result; +} + + +/** +* @brief Get Led properties +* +* @details +* - The application may call this function from simultaneous threads. +* - The implementation of this function should be lock-free. +* +* @returns +* - CTL_RESULT_SUCCESS +* - CTL_RESULT_ERROR_UNINITIALIZED +* - CTL_RESULT_ERROR_DEVICE_LOST +* - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +* + `nullptr == hLed` +* - CTL_RESULT_ERROR_INVALID_NULL_POINTER +* + `nullptr == pProperties` +*/ +ctl_result_t CTL_APICALL +ctlLedGetProperties( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + ctl_led_properties_t* pProperties ///< [in,out] Will contain Led properties. + ) +{ + ctl_result_t result = CTL_RESULT_ERROR_NOT_INITIALIZED; + + + HINSTANCE hinstLibPtr = GetLoaderHandle(); + + if (NULL != hinstLibPtr) + { + ctl_pfnLedGetProperties_t pfnLedGetProperties = (ctl_pfnLedGetProperties_t)GetProcAddress(hinstLibPtr, "ctlLedGetProperties"); + if (pfnLedGetProperties) + { + result = pfnLedGetProperties(hLed, pProperties); + } + } + + return result; +} + + +/** +* @brief Get Led state +* +* @details +* - The application may call this function from simultaneous threads. +* - The implementation of this function should be lock-free. +* +* @returns +* - CTL_RESULT_SUCCESS +* - CTL_RESULT_ERROR_UNINITIALIZED +* - CTL_RESULT_ERROR_DEVICE_LOST +* - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +* + `nullptr == hLed` +* - CTL_RESULT_ERROR_INVALID_NULL_POINTER +* + `nullptr == pState` +*/ +ctl_result_t CTL_APICALL +ctlLedGetState( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + ctl_led_state_t* pState ///< [in,out] Will contain the current Led state. + ///< Returns Led state if canControl is true and isI2C is false. + ///< pwm and color structure members of ::ctl_led_state_t will be returned + ///< only if supported by Led, else they will be returned as 0. + ) +{ + ctl_result_t result = CTL_RESULT_ERROR_NOT_INITIALIZED; + + + HINSTANCE hinstLibPtr = GetLoaderHandle(); + + if (NULL != hinstLibPtr) + { + ctl_pfnLedGetState_t pfnLedGetState = (ctl_pfnLedGetState_t)GetProcAddress(hinstLibPtr, "ctlLedGetState"); + if (pfnLedGetState) + { + result = pfnLedGetState(hLed, pState); + } + } + + return result; +} + + +/** +* @brief Set Led state +* +* @details +* - The application may call this function from simultaneous threads. +* - The implementation of this function should be lock-free. +* +* @returns +* - CTL_RESULT_SUCCESS +* - CTL_RESULT_ERROR_UNINITIALIZED +* - CTL_RESULT_ERROR_DEVICE_LOST +* - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +* + `nullptr == hLed` +* - CTL_RESULT_ERROR_INVALID_NULL_POINTER +* + `nullptr == pBuffer` +*/ +ctl_result_t CTL_APICALL +ctlLedSetState( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + void* pBuffer, ///< [in] Led State buffer. + ///< If isI2C is true, the pBuffer and bufferSize will be passed to the I2C + ///< Interface. pBuffer format in this case is OEM defined. + ///< If isI2C is false, the pBuffer will be typecasted to + ///< ::ctl_led_state_t* and bufferSize needs to be sizeof + ///< ::ctl_led_state_t. pwm and color structure members of + ///< ::ctl_led_state_t will be set only if supported by Led, else they will + ///< be ignored. + uint32_t bufferSize ///< [in] Led State buffer size. + ) +{ + ctl_result_t result = CTL_RESULT_ERROR_NOT_INITIALIZED; + + + HINSTANCE hinstLibPtr = GetLoaderHandle(); + + if (NULL != hinstLibPtr) + { + ctl_pfnLedSetState_t pfnLedSetState = (ctl_pfnLedSetState_t)GetProcAddress(hinstLibPtr, "ctlLedSetState"); + if (pfnLedSetState) + { + result = pfnLedSetState(hLed, pBuffer, bufferSize); + } + } + + return result; +} + + /** * @brief Get Video Processing capabilities * diff --git a/IntelPresentMon/ControlLib/ctlpvttemp_api.h b/IntelPresentMon/ControlLib/ctlpvttemp_api.h index f506bc66c..1d93e4d58 100644 --- a/IntelPresentMon/ControlLib/ctlpvttemp_api.h +++ b/IntelPresentMon/ControlLib/ctlpvttemp_api.h @@ -594,21 +594,13 @@ typedef struct _ctl_power_telemetry2_t ///< the write traffic to the memory modules. By taking the delta between ///< two snapshots and dividing by the delta time in seconds, an ///< application can compute the average write bandwidth. - ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from - ///< the sensor reporting the highest value. - bool vramPowerLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules are exceeding the maximum power - ///< limits. - bool vramTemperatureLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules are exceeding the temperature - ///< limits. - bool vramCurrentLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules have exceeded the power supply - ///< current limits. - bool vramVoltageLimited; ///< [out] Instantaneous indication that the memory frequency cannot be - ///< increased because the voltage limits have been reached. - bool vramUtilizationLimited; ///< [out] Instantaneous indication that due to lower memory traffic, the - ///< hardware has lowered the memory frequency. + ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the memory modules temperature, read + ///< from the sensor reporting the highest value. + bool vramPowerLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramTemperatureLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramCurrentLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramVoltageLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramUtilizationLimited; ///< [out] Deprecated / Not-supported, will always returns false ctl_oc_telemetry_item_t totalCardEnergyCounter; ///< [out] Total Card Energy Counter. ctl_psu_info_t psu[CTL_PSU_COUNT]; ///< [out] PSU voltage and power. ctl_oc_telemetry_item_t fanSpeed[CTL_FAN_COUNT];///< [out] Fan speed. diff --git a/IntelPresentMon/ControlLib/igcl_api.h b/IntelPresentMon/ControlLib/igcl_api.h index 7916c8783..66b0ede8c 100644 --- a/IntelPresentMon/ControlLib/igcl_api.h +++ b/IntelPresentMon/ControlLib/igcl_api.h @@ -144,6 +144,10 @@ typedef struct _ctl_temp_handle_t *ctl_temp_handle_t; /// @brief Handle for a device frequency domain typedef struct _ctl_freq_handle_t *ctl_freq_handle_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle for a device led +typedef struct _ctl_led_handle_t *ctl_led_handle_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Handle of a power device. typedef struct _ctl_pwr_handle_t *ctl_pwr_handle_t; @@ -476,8 +480,9 @@ typedef enum _ctl_units_t CTL_UNITS_ANGULAR_SPEED_RPM = 9, ///< Type is Angular Speed with units in Revolutions per Minute. CTL_UNITS_POWER_MILLIWATTS = 10, ///< Type is Power with units in MilliWatts. CTL_UNITS_PERCENT = 11, ///< Type is Percentage. - CTL_UNITS_MEM_SPEED_GBPS = 12, ///< Type is Memory Speed in Gigabyte per Seconds (Gbps) + CTL_UNITS_MEM_SPEED_GBPS = 12, ///< Type is Memory Speed in Gigabytes per second (GBps). CTL_UNITS_VOLTAGE_MILLIVOLTS = 13, ///< Type is Voltage with units in milliVolts. + CTL_UNITS_BANDWIDTH_MBPS = 14, ///< Type is Bandwidth in Megabytes per second (MBps). CTL_UNITS_UNKNOWN = 0x4800FFFF, ///< Type of units unknown. CTL_UNITS_MAX @@ -739,7 +744,9 @@ typedef struct _ctl_device_adapter_properties_t uint32_t num_slices; ///< [out] Number of slices char name[CTL_MAX_DEVICE_NAME_LEN]; ///< [out] Device name ctl_adapter_properties_flags_t graphics_adapter_properties; ///< [out] Graphics Adapter Properties - uint32_t Frequency; ///< [out] Clock frequency for this device. Supported only for Version > 0 + uint32_t Frequency; ///< [out] This represents the average frequency an end user may see in the + ///< typical gaming workload. Also referred as Graphics Clock. Supported + ///< only for Version > 0 uint16_t pci_subsys_id; ///< [out] PCI SubSys ID, Supported only for Version > 1 uint16_t pci_subsys_vendor_id; ///< [out] PCI SubSys Vendor ID, Supported only for Version > 1 ctl_adapter_bdf_t adapter_bdf; ///< [out] Pci Bus, Device, Function. Supported only for Version > 1 @@ -1286,6 +1293,18 @@ typedef struct _ctl_freq_state_t ctl_freq_state_t; /// @brief Forward-declare ctl_freq_throttle_time_t typedef struct _ctl_freq_throttle_time_t ctl_freq_throttle_time_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_led_properties_t +typedef struct _ctl_led_properties_t ctl_led_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_led_color_t +typedef struct _ctl_led_color_t ctl_led_color_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_led_state_t +typedef struct _ctl_led_state_t ctl_led_state_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Forward-declare ctl_video_processing_super_resolution_info_t typedef struct _ctl_video_processing_super_resolution_info_t ctl_video_processing_super_resolution_info_t; @@ -1468,10 +1487,11 @@ typedef enum _ctl_3d_feature_t typedef uint32_t ctl_3d_feature_misc_flags_t; typedef enum _ctl_3d_feature_misc_flag_t { - CTL_3D_FEATURE_MISC_FLAG_DX11 = CTL_BIT(0), ///< Feature supported on DX11 - CTL_3D_FEATURE_MISC_FLAG_DX12 = CTL_BIT(1), ///< Feature supported on DX12 - CTL_3D_FEATURE_MISC_FLAG_VULKAN = CTL_BIT(2), ///< Feature supported on VULKAN - CTL_3D_FEATURE_MISC_FLAG_LIVE_CHANGE = CTL_BIT(3), ///< User can change feature live without restarting the game + CTL_3D_FEATURE_MISC_FLAG_DX9 = CTL_BIT(0), ///< Feature supported on DX9 + CTL_3D_FEATURE_MISC_FLAG_DX11 = CTL_BIT(1), ///< Feature supported on DX11 + CTL_3D_FEATURE_MISC_FLAG_DX12 = CTL_BIT(2), ///< Feature supported on DX12 + CTL_3D_FEATURE_MISC_FLAG_VULKAN = CTL_BIT(3), ///< Feature supported on VULKAN + CTL_3D_FEATURE_MISC_FLAG_LIVE_CHANGE = CTL_BIT(4), ///< User can change feature live without restarting the game CTL_3D_FEATURE_MISC_FLAG_MAX = 0x80000000 } ctl_3d_feature_misc_flag_t; @@ -5369,6 +5389,164 @@ ctlFrequencyGetThrottleTime( #if !defined(__GNUC__) #pragma endregion // frequency #endif +// Intel 'ctlApi' for Device Adapter - Led Control +#if !defined(__GNUC__) +#pragma region led +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Led properties +typedef struct _ctl_led_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool canControl; ///< [out] Indicates if software can control the Led assuming the user has + ///< permissions. + bool isI2C; ///< [out] Indicates support for control via I2C interface. + bool isPWM; ///< [out] Returns a valid value if canControl is true and isI2C is false. + ///< Indicates if the Led is PWM capable. If isPWM is false, only turn Led + ///< on/off is supported. + bool haveRGB; ///< [out] Returns a valid value if canControl is true and isI2C is false. + ///< Indicates if the Led is RGB capable. + +} ctl_led_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Led color +typedef struct _ctl_led_color_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double red; ///< [in,out][range(0.0, 1.0)] The Led red value. On output, a value less + ///< than 0.0 indicates that the color is not known. + double green; ///< [in,out][range(0.0, 1.0)] The Led green value. On output, a value less + ///< than 0.0 indicates that the color is not known. + double blue; ///< [in,out][range(0.0, 1.0)] The Led blue value. On output, a value less + ///< than 0.0 indicates that the color is not known. + +} ctl_led_color_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Led state +typedef struct _ctl_led_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool isOn; ///< [in,out] Indicates if the Led is on or off. + double pwm; ///< [in,out] Led On/Off Ratio, PWM range(0.0, 1.0). A value greater than + ///< 1.0 is capped at 1.0. + ctl_led_color_t color; ///< [in,out] Color of the Led. + +} ctl_led_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of Leds +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumLeds( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< If count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< If count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_led_handle_t* phLed ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< If count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Led properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hLed` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlLedGetProperties( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + ctl_led_properties_t* pProperties ///< [in,out] Will contain Led properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Led state +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hLed` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlLedGetState( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + ctl_led_state_t* pState ///< [in,out] Will contain the current Led state. + ///< Returns Led state if canControl is true and isI2C is false. + ///< pwm and color structure members of ::ctl_led_state_t will be returned + ///< only if supported by Led, else they will be returned as 0. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Led state +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hLed` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pBuffer` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlLedSetState( + ctl_led_handle_t hLed, ///< [in] Handle for the component. + void* pBuffer, ///< [in] Led State buffer. + ///< If isI2C is true, the pBuffer and bufferSize will be passed to the I2C + ///< Interface. pBuffer format in this case is OEM defined. + ///< If isI2C is false, the pBuffer will be typecasted to + ///< ::ctl_led_state_t* and bufferSize needs to be sizeof + ///< ::ctl_led_state_t. pwm and color structure members of + ///< ::ctl_led_state_t will be set only if supported by Led, else they will + ///< be ignored. + uint32_t bufferSize ///< [in] Led State buffer size. + ); + + +#if !defined(__GNUC__) +#pragma endregion // led +#endif // Intel 'ctlApi' for Device Adapter #if !defined(__GNUC__) #pragma region media @@ -6092,24 +6270,33 @@ typedef struct _ctl_power_telemetry_t ///< the write traffic to the memory modules. By taking the delta between ///< two snapshots and dividing by the delta time in seconds, an ///< application can compute the average write bandwidth. - ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from - ///< the sensor reporting the highest value. - bool vramPowerLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules are exceeding the maximum power - ///< limits. - bool vramTemperatureLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules are exceeding the temperature - ///< limits. - bool vramCurrentLimited; ///< [out] Instantaneous indication that the memory frequency is being - ///< throttled because the memory modules have exceeded the power supply - ///< current limits. - bool vramVoltageLimited; ///< [out] Instantaneous indication that the memory frequency cannot be - ///< increased because the voltage limits have been reached. - bool vramUtilizationLimited; ///< [out] Instantaneous indication that due to lower memory traffic, the - ///< hardware has lowered the memory frequency. + ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the memory modules temperature, read + ///< from the sensor reporting the highest value. + bool vramPowerLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramTemperatureLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramCurrentLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramVoltageLimited; ///< [out] Deprecated / Not-supported, will always returns false + bool vramUtilizationLimited; ///< [out] Deprecated / Not-supported, will always returns false ctl_oc_telemetry_item_t totalCardEnergyCounter; ///< [out] Total Card Energy Counter. ctl_psu_info_t psu[CTL_PSU_COUNT]; ///< [out] PSU voltage and power. ctl_oc_telemetry_item_t fanSpeed[CTL_FAN_COUNT];///< [out] Fan speed. + ctl_oc_telemetry_item_t gpuVrTemp; ///< [out] GPU VR temperature. Supported for Version > 0. + ctl_oc_telemetry_item_t vramVrTemp; ///< [out] VRAM VR temperature. Supported for Version > 0. + ctl_oc_telemetry_item_t saVrTemp; ///< [out] SA VR temperature. Supported for Version > 0. + ctl_oc_telemetry_item_t gpuEffectiveClock; ///< [out] Effective frequency of the GPU. Supported for Version > 0. + ctl_oc_telemetry_item_t gpuOverVoltagePercent; ///< [out] OverVoltage as a percent between 0 and 100. Positive values + ///< represent fraction of the maximum over-voltage increment being + ///< currently applied. Zero indicates operation at or below default + ///< maximum frequency. Supported for Version > 0. + ctl_oc_telemetry_item_t gpuPowerPercent; ///< [out] GPUPower expressed as a percent representing the fraction of the + ///< default maximum power being drawn currently. Values greater than 100 + ///< indicate power draw beyond default limits. Values above OC Power limit + ///< imply throttling due to power. Supported for Version > 0. + ctl_oc_telemetry_item_t gpuTemperaturePercent; ///< [out] GPUTemperature expressed as a percent of the thermal margin. + ///< Values of 100 or greater indicate thermal throttling and 0 indicates + ///< device at 0 degree Celcius. Supported for Version > 0. + ctl_oc_telemetry_item_t vramReadBandwidth; ///< [out] VRAM Read Bandwidth. Supported for Version > 0. + ctl_oc_telemetry_item_t vramWriteBandwidth; ///< [out] VRAM Write Bandwidth. Supported for Version > 0. } ctl_power_telemetry_t; @@ -7650,6 +7837,40 @@ typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetThrottleTime_t)( ); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumLeds +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumLeds_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_led_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlLedGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnLedGetProperties_t)( + ctl_led_handle_t, + ctl_led_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlLedGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnLedGetState_t)( + ctl_led_handle_t, + ctl_led_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlLedSetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnLedSetState_t)( + ctl_led_handle_t, + void*, + uint32_t + ); + + /////////////////////////////////////////////////////////////////////////////// /// @brief Function-pointer for ctlGetSupportedVideoProcessingCapabilities typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedVideoProcessingCapabilities_t)( diff --git a/IntelPresentMon/Core/source/infra/LogSetup.cpp b/IntelPresentMon/Core/source/infra/LogSetup.cpp index 9868127d4..acedcfea0 100644 --- a/IntelPresentMon/Core/source/infra/LogSetup.cpp +++ b/IntelPresentMon/Core/source/infra/LogSetup.cpp @@ -119,8 +119,8 @@ namespace p2c infra::util::FolderResolver::Folder::App, L"logs\\"); } // always enable the logfile for client - const auto logfileNameClient = bool(opt.cefType) ? std::format(L"log-{}-{}.txt", - str::ToWide(*opt.cefType), GetCurrentProcessId()) : L"log.txt"s; + const auto logfileNameClient = bool(opt.cefType) ? std::format(L"pmlog-{}-{}.txt", + str::ToWide(*opt.cefType), GetCurrentProcessId()) : L"pmlog.txt"s; const auto logfilePathClient = std::filesystem::path{ logFolder } / logfileNameClient; pChan->AttachComponent(std::make_shared(std::make_shared(), std::make_shared(logfilePathClient)), "drv:file"); @@ -165,7 +165,7 @@ namespace p2c } } // enable logfile for middleware if we're not doing the copy connection - if (!opt.logMiddlewareCopy) { + if (!opt.logMiddlewareCopy && *opt.cefType == "renderer") { if (auto sta = pmSetupFileLogging(logFolder.string().c_str(), (PM_DIAGNOSTIC_LEVEL)pol.GetLogLevel(), (PM_DIAGNOSTIC_LEVEL)pol.GetTraceLevel(), diff --git a/IntelPresentMon/Interprocess/source/IntrospectionCapsLookup.h b/IntelPresentMon/Interprocess/source/IntrospectionCapsLookup.h index 0e89944ff..7d5c36ee4 100644 --- a/IntelPresentMon/Interprocess/source/IntrospectionCapsLookup.h +++ b/IntelPresentMon/Interprocess/source/IntrospectionCapsLookup.h @@ -16,6 +16,7 @@ namespace pmon::ipc::intro template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_voltage; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_temperature; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_frequency; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_effective_frequency; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_utilization; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_render_compute_utilization; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_media_utilization; }; @@ -23,11 +24,20 @@ namespace pmon::ipc::intro template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::vram_voltage; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::vram_frequency; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::vram_effective_frequency; }; - template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::vram_temperature; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_voltage_regulator_temperature; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_mem_effective_bandwidth; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_overvoltage_percent; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_temperature_percent; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_power_percent; }; + template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_card_power; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBitArray = std::array{ GpuTelemetryCapBits::fan_speed_0, GpuTelemetryCapBits::fan_speed_1, GpuTelemetryCapBits::fan_speed_2, GpuTelemetryCapBits::fan_speed_3, GpuTelemetryCapBits::fan_speed_4, }; }; + template<> struct IntrospectionCapsLookup { + static constexpr auto gpuCapBitArray = std::array{ GpuTelemetryCapBits::max_fan_speed_0, GpuTelemetryCapBits::max_fan_speed_1, + GpuTelemetryCapBits::max_fan_speed_2, GpuTelemetryCapBits::max_fan_speed_3, GpuTelemetryCapBits::max_fan_speed_4, }; + }; //template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBitArray = std::array{ // GpuTelemetryCapBits::psu_info_0, GpuTelemetryCapBits::psu_info_1, GpuTelemetryCapBits::psu_info_2, GpuTelemetryCapBits::psu_info_3, GpuTelemetryCapBits::psu_info_4, }; }; template<> struct IntrospectionCapsLookup { static constexpr auto gpuCapBit = GpuTelemetryCapBits::gpu_mem_size; }; diff --git a/IntelPresentMon/Interprocess/source/metadata/MetricList.h b/IntelPresentMon/Interprocess/source/metadata/MetricList.h index 80519f9b0..28a184994 100644 --- a/IntelPresentMon/Interprocess/source/metadata/MetricList.h +++ b/IntelPresentMon/Interprocess/source/metadata/MetricList.h @@ -87,4 +87,12 @@ X_(PM_METRIC_CPU_CORE_UTILITY, PM_METRIC_TYPE_DYNAMIC, PM_UNIT_PERCENT, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_VOID, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \ X_(PM_METRIC_ALL_INPUT_TO_PHOTON_LATENCY, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, PM_STAT_NON_ZERO_AVG, PM_STAT_PERCENTILE_01, PM_STAT_PERCENTILE_05, PM_STAT_PERCENTILE_10, PM_STAT_MAX) \ \ - X_(PM_METRIC_INSTRUMENTED_LATENCY, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \ No newline at end of file + X_(PM_METRIC_INSTRUMENTED_LATENCY, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MILLISECONDS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_INDEPENDENT, FULL_STATS) \ + X_(PM_METRIC_GPU_EFFECTIVE_FREQUENCY, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_MEGAHERTZ, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_CELSIUS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_GIGABITS_PER_SECOND, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_OVERVOLTAGE_PERCENT, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_PERCENT, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_TEMPERATURE_PERCENT, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_PERCENT, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_POWER_PERCENT, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_PERCENT, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_FAN_SPEED_PERCENT, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_PERCENT, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ + X_(PM_METRIC_GPU_CARD_POWER, PM_METRIC_TYPE_DYNAMIC_FRAME, PM_UNIT_WATTS, PM_DATA_TYPE_DOUBLE, PM_DATA_TYPE_DOUBLE, 0, PM_DEVICE_TYPE_GRAPHICS_ADAPTER, FULL_STATS) \ No newline at end of file diff --git a/IntelPresentMon/PresentMonAPI2/Internal.h b/IntelPresentMon/PresentMonAPI2/Internal.h index 7ddd47911..59b916636 100644 --- a/IntelPresentMon/PresentMonAPI2/Internal.h +++ b/IntelPresentMon/PresentMonAPI2/Internal.h @@ -1,5 +1,6 @@ #pragma once #include "PresentMonAPI.h" +#include "PresentMonDiagnostics.h" #include "../CommonUtilities/log/Log.h" #include "../CommonUtilities/log/LineTable.h" #include "../CommonUtilities/log/GlobalPolicy.h" @@ -38,4 +39,5 @@ PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_( // function to flush the dll's log channel worker queue when before exiting PRESENTMON_API2_EXPORT void pmFlushEntryPoint_() noexcept; // set middleware to log using OutputDebugString -PRESENTMON_API2_EXPORT void pmSetupODSLogging_(); +PRESENTMON_API2_EXPORT void pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL logLevel, + PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace); diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp index 01d8da22a..8d23d858c 100644 --- a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp +++ b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp @@ -5,10 +5,12 @@ #include "../Interprocess/source/PmStatusError.h" #include "Internal.h" #include "PresentMonAPI.h" +#include "PresentMonDiagnostics.h" #include "../PresentMonMiddleware/LogSetup.h" #include "../Versioning/PresentMonAPIVersion.h" + using namespace pmon; using namespace pmon::mid; @@ -77,6 +79,7 @@ PRESENTMON_API2_EXPORT PM_STATUS pmOpenSession_(PM_SESSION_HANDLE* pHandle, cons pMiddleware = std::make_shared(std::move(pipeName), std::move(introNsm)); *pHandle = pMiddleware.get(); handleMap_[*pHandle] = std::move(pMiddleware); + pmlog_info("Middleware successfully opened session with service"); return PM_STATUS_SUCCESS; } catch (...) { @@ -136,9 +139,11 @@ PRESENTMON_API2_EXPORT void pmFlushEntryPoint_() noexcept pmon::util::log::FlushEntryPoint(); } -PRESENTMON_API2_EXPORT void pmSetupODSLogging_() +PRESENTMON_API2_EXPORT void pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL logLevel, + PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace) { - pmon::util::log::SetupODSChannel(); + pmon::util::log::SetupODSChannel((pmon::util::log::Level)logLevel, + (pmon::util::log::Level)stackTraceLevel, exceptionTrace); } // public endpoints diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h index a94e5360f..52e7bc4f0 100644 --- a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h +++ b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.h @@ -124,6 +124,14 @@ extern "C" { PM_METRIC_INSTRUMENTED_LATENCY, PM_METRIC_ANIMATION_TIME, + PM_METRIC_GPU_EFFECTIVE_FREQUENCY, + PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE, + PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH, + PM_METRIC_GPU_OVERVOLTAGE_PERCENT, + PM_METRIC_GPU_TEMPERATURE_PERCENT, + PM_METRIC_GPU_POWER_PERCENT, + PM_METRIC_GPU_FAN_SPEED_PERCENT, + PM_METRIC_GPU_CARD_POWER, }; enum PM_METRIC_TYPE diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonDiagnostics.cpp b/IntelPresentMon/PresentMonAPI2/PresentMonDiagnostics.cpp index 1570e5f00..39ef91786 100644 --- a/IntelPresentMon/PresentMonAPI2/PresentMonDiagnostics.cpp +++ b/IntelPresentMon/PresentMonAPI2/PresentMonDiagnostics.cpp @@ -1,4 +1,5 @@ #include "PresentMonDiagnostics.h" +#include "../CommonUtilities/win/WinAPI.h" #include "../CommonUtilities/log/DiagnosticDriver.h" #include "../CommonUtilities/log/Log.h" #include "../CommonUtilities/Exception.h" @@ -129,11 +130,12 @@ PRESENTMON_API2_EXPORT PM_STATUS pmDiagnosticUnblockWaitingThread() PRESENTMON_API2_EXPORT PM_STATUS pmSetupFileLogging(const char* path, PM_DIAGNOSTIC_LEVEL logLevel, PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace) { - auto fsPath = std::filesystem::path(path); + const auto fsPath = std::filesystem::path(path); if (!std::filesystem::is_directory(fsPath)) { return PM_STATUS_NONEXISTENT_FILE_PATH; } - log::SetupFileChannel(std::move(fsPath), GetLogLevel_(logLevel), + auto file = fsPath / std::format("pmlog-mid-{}.txt", GetCurrentProcessId()); + log::SetupFileChannel(std::move(file), GetLogLevel_(logLevel), GetLogLevel_(stackTraceLevel), exceptionTrace); return PM_STATUS_SUCCESS; } diff --git a/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp b/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp index 5b62766d1..91daf4da7 100644 --- a/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp +++ b/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp @@ -58,7 +58,7 @@ _CrtMemState(*pFunc_pmCreateHeapCheckpoint__)() = nullptr; LoggingSingletons(*pFunc_pmLinkLogging__)(std::shared_ptr, std::function) = nullptr; void(*pFunc_pmFlushEntryPoint__)() = nullptr; -void(*pFunc_pmSetupODSLogging__)() = nullptr; +void(*pFunc_pmSetupODSLogging__)(PM_DIAGNOSTIC_LEVEL, PM_DIAGNOSTIC_LEVEL, bool) = nullptr; // internal loader state globals @@ -312,14 +312,15 @@ PRESENTMON_API2_EXPORT void pmFlushEntryPoint_() noexcept pFunc_pmFlushEntryPoint__(); } } -PRESENTMON_API2_EXPORT void pmSetupODSLogging_() +PRESENTMON_API2_EXPORT void pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL logLevel, + PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace) { if (!middlewareLoadedSuccessfully_) { if (auto status = LoadLibrary_(); status != PM_STATUS_SUCCESS) { throw LoaderExcept_(status); } } - pFunc_pmSetupODSLogging__(); + pFunc_pmSetupODSLogging__(logLevel, stackTraceLevel, exceptionTrace); } PRESENTMON_API2_EXPORT PM_STATUS pmDiagnosticSetup(const PM_DIAGNOSTIC_CONFIGURATION* pConfig) { diff --git a/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp b/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp index d8b563307..fa9e14128 100644 --- a/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp +++ b/IntelPresentMon/PresentMonAPI2Tests/EtlTests.cpp @@ -275,7 +275,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -315,7 +315,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -361,7 +361,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -457,7 +457,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -505,7 +505,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -553,7 +553,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -601,7 +601,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -649,7 +649,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -697,7 +697,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -745,7 +745,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -793,7 +793,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -841,7 +841,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -889,7 +889,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -938,7 +938,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -986,7 +986,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1034,7 +1034,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1082,7 +1082,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1130,7 +1130,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1178,7 +1178,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1226,7 +1226,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1274,7 +1274,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1322,7 +1322,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1370,7 +1370,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1418,7 +1418,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1466,7 +1466,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1514,7 +1514,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1562,7 +1562,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1610,7 +1610,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1658,7 +1658,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1706,7 +1706,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1756,7 +1756,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1806,7 +1806,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -1856,7 +1856,7 @@ namespace EtlTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { diff --git a/IntelPresentMon/PresentMonAPI2Tests/RealtimeMetricTests.cpp b/IntelPresentMon/PresentMonAPI2Tests/RealtimeMetricTests.cpp index 202015191..0e39d1903 100644 --- a/IntelPresentMon/PresentMonAPI2Tests/RealtimeMetricTests.cpp +++ b/IntelPresentMon/PresentMonAPI2Tests/RealtimeMetricTests.cpp @@ -128,7 +128,7 @@ namespace RealtimeMetricTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -175,7 +175,7 @@ namespace RealtimeMetricTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { @@ -236,7 +236,7 @@ namespace RealtimeMetricTests try { pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); pSession = std::make_unique(pipeName.c_str(), introName.c_str()); } catch (const std::exception& e) { diff --git a/IntelPresentMon/PresentMonAPI2Tests/WrapperIntrospectionTests.cpp b/IntelPresentMon/PresentMonAPI2Tests/WrapperIntrospectionTests.cpp index eedbbce2c..96107a07b 100644 --- a/IntelPresentMon/PresentMonAPI2Tests/WrapperIntrospectionTests.cpp +++ b/IntelPresentMon/PresentMonAPI2Tests/WrapperIntrospectionTests.cpp @@ -49,7 +49,7 @@ namespace EndToEndTests std::this_thread::sleep_for(100ms); pmLoaderSetPathToMiddlewareDll_("./PresentMonAPI2.dll"); - pmSetupODSLogging_(); + pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL_DEBUG, PM_DIAGNOSTIC_LEVEL_ERROR, false); oSession.emplace(ctlPipeName, introName); pData = oSession->GetIntrospectionRoot(); diff --git a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp index c63b3716f..5c895f36d 100644 --- a/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp +++ b/IntelPresentMon/PresentMonMiddleware/ConcreteMiddleware.cpp @@ -391,6 +391,47 @@ namespace pmon::mid break; } break; + case PM_METRIC_GPU_FAN_SPEED_PERCENT: + switch (qe.arrayIndex) + { + case 0: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::max_fan_speed_0)); + break; + case 1: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::max_fan_speed_1)); + break; + case 2: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::max_fan_speed_2)); + break; + case 3: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::max_fan_speed_3)); + break; + case 4: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::max_fan_speed_4)); + break; + } + break; + case PM_METRIC_GPU_EFFECTIVE_FREQUENCY: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_effective_frequency)); + break; + case PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_voltage_regulator_temperature)); + break; + case PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_mem_effective_bandwidth)); + break; + case PM_METRIC_GPU_OVERVOLTAGE_PERCENT: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_overvoltage_percent)); + break; + case PM_METRIC_GPU_TEMPERATURE_PERCENT: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_temperature_percent)); + break; + case PM_METRIC_GPU_POWER_PERCENT: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_power_percent)); + break; + case PM_METRIC_GPU_CARD_POWER: + pQuery->accumGpuBits.set(static_cast(GpuTelemetryCapBits::gpu_card_power)); + break; case PM_METRIC_CPU_UTILIZATION: pQuery->accumCpuBits.set(static_cast(CpuTelemetryCapBits::cpu_utilization)); break; @@ -1516,6 +1557,26 @@ static void ReportMetrics( case GpuTelemetryCapBits::fan_speed_4: metricInfo[PM_METRIC_GPU_FAN_SPEED].data[4].emplace_back(power_telemetry_info.fan_speed_rpm[4]); break; + case GpuTelemetryCapBits::max_fan_speed_0: + metricInfo[PM_METRIC_GPU_FAN_SPEED_PERCENT].data[0].emplace_back( + power_telemetry_info.fan_speed_rpm[0] / double(power_telemetry_info.max_fan_speed_rpm[0])); + break; + case GpuTelemetryCapBits::max_fan_speed_1: + metricInfo[PM_METRIC_GPU_FAN_SPEED_PERCENT].data[1].emplace_back( + power_telemetry_info.fan_speed_rpm[0] / double(power_telemetry_info.max_fan_speed_rpm[1])); + break; + case GpuTelemetryCapBits::max_fan_speed_2: + metricInfo[PM_METRIC_GPU_FAN_SPEED_PERCENT].data[2].emplace_back( + power_telemetry_info.fan_speed_rpm[0] / double(power_telemetry_info.max_fan_speed_rpm[2])); + break; + case GpuTelemetryCapBits::max_fan_speed_3: + metricInfo[PM_METRIC_GPU_FAN_SPEED_PERCENT].data[3].emplace_back( + power_telemetry_info.fan_speed_rpm[0] / double(power_telemetry_info.max_fan_speed_rpm[3])); + break; + case GpuTelemetryCapBits::max_fan_speed_4: + metricInfo[PM_METRIC_GPU_FAN_SPEED_PERCENT].data[4].emplace_back( + power_telemetry_info.fan_speed_rpm[0] / double(power_telemetry_info.max_fan_speed_rpm[4])); + break; case GpuTelemetryCapBits::gpu_mem_used: metricInfo[PM_METRIC_GPU_MEM_USED].data[0].emplace_back(static_cast(power_telemetry_info.gpu_mem_used_b)); break; @@ -1555,6 +1616,27 @@ static void ReportMetrics( case GpuTelemetryCapBits::vram_utilization_limited: metricInfo[PM_METRIC_GPU_MEM_UTILIZATION_LIMITED].data[0].emplace_back(power_telemetry_info.vram_utilization_limited); break; + case GpuTelemetryCapBits::gpu_effective_frequency: + metricInfo[PM_METRIC_GPU_EFFECTIVE_FREQUENCY].data[0].emplace_back(power_telemetry_info.gpu_effective_frequency_mhz); + break; + case GpuTelemetryCapBits::gpu_voltage_regulator_temperature: + metricInfo[PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE].data[0].emplace_back(power_telemetry_info.gpu_voltage_regulator_temperature_c); + break; + case GpuTelemetryCapBits::gpu_mem_effective_bandwidth: + metricInfo[PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH].data[0].emplace_back(power_telemetry_info.gpu_mem_effective_bandwidth_gbps); + break; + case GpuTelemetryCapBits::gpu_overvoltage_percent: + metricInfo[PM_METRIC_GPU_OVERVOLTAGE_PERCENT].data[0].emplace_back(power_telemetry_info.gpu_overvoltage_percent); + break; + case GpuTelemetryCapBits::gpu_temperature_percent: + metricInfo[PM_METRIC_GPU_TEMPERATURE_PERCENT].data[0].emplace_back(power_telemetry_info.gpu_temperature_percent); + break; + case GpuTelemetryCapBits::gpu_power_percent: + metricInfo[PM_METRIC_GPU_POWER_PERCENT].data[0].emplace_back(power_telemetry_info.gpu_power_percent); + break; + case GpuTelemetryCapBits::gpu_card_power: + metricInfo[PM_METRIC_GPU_CARD_POWER].data[0].emplace_back(power_telemetry_info.gpu_card_power_w); + break; default: validGpuMetric = false; break; @@ -1774,6 +1856,7 @@ static void ReportMetrics( { case PM_METRIC_GPU_POWER: case PM_METRIC_GPU_FAN_SPEED: + case PM_METRIC_GPU_FAN_SPEED_PERCENT: case PM_METRIC_GPU_VOLTAGE: case PM_METRIC_GPU_FREQUENCY: case PM_METRIC_GPU_TEMPERATURE: @@ -1803,6 +1886,13 @@ static void ReportMetrics( case PM_METRIC_CPU_TEMPERATURE: case PM_METRIC_CPU_FREQUENCY: case PM_METRIC_CPU_CORE_UTILITY: + case PM_METRIC_GPU_EFFECTIVE_FREQUENCY: + case PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE: + case PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH: + case PM_METRIC_GPU_OVERVOLTAGE_PERCENT: + case PM_METRIC_GPU_TEMPERATURE_PERCENT: + case PM_METRIC_GPU_POWER_PERCENT: + case PM_METRIC_GPU_CARD_POWER: CalculateGpuCpuMetric(metricInfo, qe, pBlob); break; case PM_METRIC_CPU_VENDOR: @@ -1821,8 +1911,8 @@ static void ReportMetrics( { auto& output = reinterpret_cast(pBlob[qe.dataOffset]); output = CalcGpuMemUtilization(qe.stat); + break; } - break; default: break; } diff --git a/IntelPresentMon/PresentMonMiddleware/LogSetup.cpp b/IntelPresentMon/PresentMonMiddleware/LogSetup.cpp index dee117ddb..c694fe27e 100644 --- a/IntelPresentMon/PresentMonMiddleware/LogSetup.cpp +++ b/IntelPresentMon/PresentMonMiddleware/LogSetup.cpp @@ -84,13 +84,15 @@ namespace pmon::util::log const auto pFormatter = std::make_shared(); const auto pFileStrategy = std::make_shared(std::move(path)); pChannel->AttachComponent(std::make_shared(pFormatter, pFileStrategy), "drv:file"); + // also add debugger output, just in case (it's low overhead) + pChannel->AttachComponent(std::make_shared(pFormatter), "drv:dbg"); return pChannel; } catch (...) { return {}; } } - // create a channel that via the diagnostic layer + // create a channel that outputs via the diagnostic layer std::shared_ptr MakeDiagnosticChannel_(std::shared_ptr pDiag) noexcept { try { @@ -128,11 +130,11 @@ namespace pmon::util::log InjectDefaultChannel(MakeCopyChannel_(std::move(pCopyTargetChannel))); } - void SetupODSChannel() noexcept + void SetupODSChannel(Level logLevel, Level stackTraceLevel, bool exceptionTrace) noexcept { - // reset logging level when channel is explicitly requested - GlobalPolicy::Get().SetLogLevelDefault(); - GlobalPolicy::Get().SetTraceLevelDefault(); + GlobalPolicy::Get().SetLogLevel(logLevel); + GlobalPolicy::Get().SetTraceLevel(stackTraceLevel); + GlobalPolicy::Get().SetExceptionTrace(exceptionTrace); InjectDefaultChannel(MakeODSChannel_()); } diff --git a/IntelPresentMon/PresentMonMiddleware/LogSetup.h b/IntelPresentMon/PresentMonMiddleware/LogSetup.h index 2c2616a78..c522d0adc 100644 --- a/IntelPresentMon/PresentMonMiddleware/LogSetup.h +++ b/IntelPresentMon/PresentMonMiddleware/LogSetup.h @@ -6,7 +6,7 @@ namespace pmon::util::log { void SetupCopyChannel(std::shared_ptr pCopyTargetChannel) noexcept; - void SetupODSChannel() noexcept; + void SetupODSChannel(Level logLevel, Level stackTraceLevel, bool exceptionTrace) noexcept; void SetupDiagnosticChannel(const PM_DIAGNOSTIC_CONFIGURATION* pConfig) noexcept; void SetupFileChannel(std::filesystem::path path, Level logLevel, Level stackTraceLevel, bool exceptionTrace) noexcept; diff --git a/IntelPresentMon/UnitTests/Timing.cpp b/IntelPresentMon/UnitTests/Timing.cpp index 6f70aea3d..0118d7f3f 100644 --- a/IntelPresentMon/UnitTests/Timing.cpp +++ b/IntelPresentMon/UnitTests/Timing.cpp @@ -94,7 +94,7 @@ namespace UtilityTests Sleep(16); waiter.Wait(); const auto dur = std::chrono::duration(Timer::now() - start).count(); - AssertWithinTolerance(dur, waitInterval * (i + 1), 0.000'01); + AssertWithinTolerance(dur, waitInterval * (i + 1), 0.000'02); } } // TODO: interval waiter test with late Wait() call diff --git a/IntelPresentMon/metrics.csv b/IntelPresentMon/metrics.csv index 225699bb3..450b56230 100644 --- a/IntelPresentMon/metrics.csv +++ b/IntelPresentMon/metrics.csv @@ -41,7 +41,7 @@ PM_METRIC_CPU_VENDOR,1,CPU Vendor,Vendor name of the CPU. PM_METRIC_CPU_NAME,1,CPU Name,Device name of the CPU. ,,, PM_METRIC_GPU_SUSTAINED_POWER_LIMIT,1,GPU Sustained Power Limit,Sustained power limit of the GPU. -PM_METRIC_GPU_POWER,1,GPU Power,Power consumed by the graphics adapter. +PM_METRIC_GPU_POWER,1,GPU Power,Power consumed by the graphics processing unit. PM_METRIC_GPU_VOLTAGE,1,GPU Voltage,Voltage consumed by the graphics adapter. PM_METRIC_GPU_FREQUENCY,1,GPU Frequency,Clock speed of the GPU cores. PM_METRIC_GPU_TEMPERATURE,1,GPU Temperature,Temperature of the GPU. @@ -82,4 +82,12 @@ PM_METRIC_CPU_TEMPERATURE,1,CPU Temperature,Temperature of the CPU. PM_METRIC_CPU_FREQUENCY,1,CPU Frequency,Clock speed of the CPU. PM_METRIC_CPU_CORE_UTILITY,1,CPU Core Utility,Amount of CPU processing utility being used per core. ,,, -PM_METRIC_INSTRUMENTED_LATENCY,,Instrumented Latency,Instrumented Frame Start To Display Latency,How long it took from the instrumented start of this frame until the frame was displayed on the screen. \ No newline at end of file +PM_METRIC_INSTRUMENTED_LATENCY,,Instrumented Latency,Instrumented Frame Start To Display Latency,How long it took from the instrumented start of this frame until the frame was displayed on the screen. +PM_METRIC_GPU_EFFECTIVE_FREQUENCY,1,GPU Effective Frequency,Effective clock speed of the GPU cores. +PM_METRIC_GPU_VOLTAGE_REGULATOR_TEMPERATURE,1,GPU Voltage Regulator Temperature,Effective clock speed of the GPU cores. +PM_METRIC_GPU_MEM_EFFECTIVE_BANDWIDTH,1,GPU Memory Effective Bandwidth,Data transfer rate that the memory modules can sustain based on current clock frequency. +PM_METRIC_GPU_OVERVOLTAGE_PERCENT,1,GPU Overvoltage Percent,GPU overvoltage increment as a ratio of the maximum increment. +PM_METRIC_GPU_TEMPERATURE_PERCENT,1,GPU Temperature Percent,GPU temperature as a ratio of the thermal margin. +PM_METRIC_GPU_POWER_PERCENT,1,GPU Power Percent,GPU power draw as a ratio of default maximum power. +PM_METRIC_GPU_FAN_SPEED_PERCENT,1,GPU Fan Speed Percent,GPU fan speed as a ratio of the max speed for that fan. +PM_METRIC_GPU_CARD_POWER,1,GPU Card Power,Total power consumption of the graphics adapter board. \ No newline at end of file diff --git a/PresentMon.sln b/PresentMon.sln index b4bd7ee90..6e5a7d2fb 100644 --- a/PresentMon.sln +++ b/PresentMon.sln @@ -67,6 +67,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{B4CC5828-9638-42EC-A692-E81E8227DD84}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + IntelPresentMon\metrics.csv = IntelPresentMon\metrics.csv vcpkg.json = vcpkg.json EndProjectSection EndProject