/// <summary> /// Reads EDID data of an output /// </summary> /// <param name="output">The GPU output to read EDID information for</param> /// <returns>A byte array containing EDID data</returns> public byte[] ReadEDIDData(GPUOutput output) { try { var data = new byte[0]; var identification = 0; var totalSize = EDIDV3.MaxDataSize; for (var offset = 0; offset < totalSize; offset += EDIDV3.MaxDataSize) { var edid = GPUApi.GetEDID(Handle, output.OutputId, offset, identification); identification = edid.Identification; totalSize = edid.TotalSize; var edidData = edid.Data; Array.Resize(ref data, data.Length + edidData.Length); Array.Copy(edidData, 0, data, data.Length - edidData.Length, edidData.Length); } return(data); } catch (NVIDIAApiException ex) { if (ex.Status == Status.IncompatibleStructureVersion) { return(GPUApi.GetEDID(Handle, output.OutputId).Data); } throw; } }
/// <summary> /// Changes a cooler settings by modifying the policy and the current level /// </summary> /// <param name="coolerId">The cooler identification number (index) to change the settings.</param> /// <param name="policy">The new cooler policy.</param> /// <param name="newLevel">The new cooler level. Valid only if policy is set to manual.</param> // ReSharper disable once TooManyDeclarations public void SetCoolerSettings(int coolerId, CoolerPolicy policy, int newLevel) { if (Coolers.All(cooler => cooler.CoolerId != coolerId)) { throw new ArgumentException("Invalid cooler identification number provided.", nameof(coolerId)); } try { GPUApi.SetCoolerLevels( PhysicalGPU.Handle, (uint)coolerId, new PrivateCoolerLevelsV1(new[] { new PrivateCoolerLevelsV1.CoolerLevel(policy, (uint)newLevel) } ), 1 ); return; } catch (NVIDIAApiException e) { if (e.Status != Status.NotSupported) { throw; } } var currentControl = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle); var newControl = new PrivateFanCoolersControlV1( currentControl.FanCoolersControlEntries.Select( entry => entry.CoolerId == coolerId ? new PrivateFanCoolersControlV1.FanCoolersControlEntry( entry.CoolerId, policy == CoolerPolicy.Manual ? FanCoolersControlMode.Manual : FanCoolersControlMode.Auto, policy == CoolerPolicy.Manual ? (uint)newLevel : 0u) : entry ) .ToArray(), currentControl.UnknownUInt ); GPUApi.SetClientFanCoolersControl(PhysicalGPU.Handle, newControl); }
private void WriteEDIDData(uint displayOutputId, byte[] edidData) { try { for (var offset = 0; offset < edidData.Length; offset += EDIDV3.MaxDataSize) { var array = new byte[Math.Min(EDIDV3.MaxDataSize, edidData.Length - offset)]; Array.Copy(edidData, offset, array, 0, array.Length); var instance = EDIDV3.CreateWithData(0, (uint)offset, array, edidData.Length); GPUApi.SetEDID(Handle, displayOutputId, instance); } return; } catch (NVIDIAApiException ex) { if (ex.Status != Status.IncompatibleStructureVersion) { throw; } } catch (NVIDIANotSupportedException) { // ignore } try { for (var offset = 0; offset < edidData.Length; offset += EDIDV2.MaxDataSize) { var array = new byte[Math.Min(EDIDV2.MaxDataSize, edidData.Length - offset)]; Array.Copy(edidData, offset, array, 0, array.Length); GPUApi.SetEDID(Handle, displayOutputId, EDIDV2.CreateWithData(array, edidData.Length)); } return; } catch (NVIDIAApiException ex) { if (ex.Status != Status.IncompatibleStructureVersion) { throw; } } catch (NVIDIANotSupportedException) { // ignore } GPUApi.SetEDID(Handle, displayOutputId, EDIDV1.CreateWithData(edidData)); }
/// <summary> /// Resets one or more cooler settings to default. /// </summary> /// <param name="coolerIds">The cooler identification numbers (indexes) to reset their settings to default.</param> public void RestoreCoolerSettingsToDefault(params int[] coolerIds) { var availableCoolerIds = Coolers.Select(cooler => cooler.CoolerId).ToArray(); if (coolerIds.Any(i => !availableCoolerIds.Contains(i))) { throw new ArgumentException("Invalid cooler identification number provided.", nameof(coolerIds)); } try { GPUApi.RestoreCoolerSettings(PhysicalGPU.Handle, coolerIds.Select(i => (uint)i).ToArray()); return; } catch (NVIDIAApiException e) { if (e.Status != Status.NotSupported) { throw; } } var currentControl = GPUApi.GetClientFanCoolersControl(PhysicalGPU.Handle); var newControl = new PrivateFanCoolersControlV1( currentControl.FanCoolersControlEntries.Select( entry => coolerIds.Contains((int)entry.CoolerId) ? new PrivateFanCoolersControlV1.FanCoolersControlEntry( entry.CoolerId, FanCoolersControlMode.Auto ) : entry ) .ToArray(), currentControl.UnknownUInt ); GPUApi.SetClientFanCoolersControl(PhysicalGPU.Handle, newControl); }
public override void Update() { NvGPUThermalSettings settings = GetThermalSettings(); foreach (Sensor sensor in temperatures) { sensor.Value = settings.Sensor[sensor.Index].CurrentTemp; } bool tachReadingOk = false; if (NVAPI.NvAPI_GPU_GetTachReading != null && NVAPI.NvAPI_GPU_GetTachReading(handle, out int fanValue) == NvStatus.OK) { fan.Value = fanValue; ActivateSensor(fan); tachReadingOk = true; } uint[] values = GetClocks(); if (values != null) { clocks[1].Value = 0.001f * values[8]; if (values[30] != 0) { clocks[0].Value = 0.0005f * values[30]; clocks[2].Value = 0.001f * values[30]; } else { clocks[0].Value = 0.001f * values[0]; clocks[2].Value = 0.001f * values[14]; } } // set extra sensors from external NvAPI wrapper if (physicalGPU != null) { try { voltage.Value = GPUApi.GetCurrentVoltage(physicalGPU.Handle).ValueInMicroVolt / 1E06f; ActivateSensor(voltage); var currentActiveLimit = physicalGPU.PerformanceControl.CurrentActiveLimit; powerLimit.Value = ((currentActiveLimit & PerformanceLimit.PowerLimit) == PerformanceLimit.PowerLimit) ? 1 : 0; ActivateSensor(powerLimit); temperatureLimit.Value = ((currentActiveLimit & PerformanceLimit.TemperatureLimit) == PerformanceLimit.TemperatureLimit) ? 1 : 0; ActivateSensor(temperatureLimit); voltageLimit.Value = ((currentActiveLimit & PerformanceLimit.VoltageLimit) == PerformanceLimit.VoltageLimit) ? 1 : 0; ActivateSensor(voltageLimit); } catch { voltage.Value = float.NaN; powerLimit.Value = float.NaN; temperatureLimit.Value = float.NaN; voltageLimit.Value = float.NaN; } } var infoEx = new NvDynamicPstatesInfoEx(); infoEx.Version = NVAPI.GPU_DYNAMIC_PSTATES_INFO_EX_VER; infoEx.UtilizationDomains = new NvUtilizationDomainEx[NVAPI.NVAPI_MAX_GPU_UTILIZATIONS]; if (NVAPI.NvAPI_GPU_GetDynamicPstatesInfoEx != null && NVAPI.NvAPI_GPU_GetDynamicPstatesInfoEx(handle, ref infoEx) == NvStatus.OK) { for (int i = 0; i < loads.Length; i++) { if (infoEx.UtilizationDomains[i].Present) { loads[i].Value = infoEx.UtilizationDomains[i].Percentage; ActivateSensor(loads[i]); } } } else { var info = new NvDynamicPstatesInfo { Version = NVAPI.GPU_DYNAMIC_PSTATES_INFO_VER, UtilizationDomains = new NvUtilizationDomain[NVAPI.NVAPI_MAX_GPU_UTILIZATIONS] }; if (NVAPI.NvAPI_GPU_GetDynamicPstatesInfo != null && NVAPI.NvAPI_GPU_GetDynamicPstatesInfo(handle, ref info) == NvStatus.OK) { for (int i = 0; i < loads.Length; i++) { if (info.UtilizationDomains[i].Present) { loads[i].Value = info.UtilizationDomains[i].Percentage; ActivateSensor(loads[i]); } } } } var coolerSettings = GetCoolerSettings(); var coolerSettingsOk = false; if (coolerSettings.Count > 0) { control.Value = coolerSettings.Cooler[0].CurrentLevel; ActivateSensor(control); coolerSettingsOk = true; } if (!tachReadingOk || !coolerSettingsOk) { var coolersStatus = GetFanCoolersStatus(); if (coolersStatus.Count > 0) { if (!coolerSettingsOk) { control.Value = coolersStatus.Items[0].CurrentLevel; ActivateSensor(control); coolerSettingsOk = true; } if (!tachReadingOk) { fan.Value = coolersStatus.Items[0].CurrentRpm; ActivateSensor(fan); tachReadingOk = true; } } } NvDisplayDriverMemoryInfo memoryInfo = new NvDisplayDriverMemoryInfo { Version = NVAPI.DISPLAY_DRIVER_MEMORY_INFO_VER, Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU] }; if (NVAPI.NvAPI_GetDisplayDriverMemoryInfo != null && displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverMemoryInfo(displayHandle.Value, ref memoryInfo) == NvStatus.OK) { uint totalMemory = memoryInfo.Values[0]; uint freeMemory = memoryInfo.Values[4]; float usedMemory = Math.Max(totalMemory - freeMemory, 0); memoryFree.Value = (float)freeMemory / 1024; memoryAvail.Value = (float)totalMemory / 1024; memoryUsed.Value = usedMemory / 1024; memoryLoad.Value = 100f * usedMemory / totalMemory; ActivateSensor(memoryAvail); ActivateSensor(memoryUsed); ActivateSensor(memoryFree); ActivateSensor(memoryLoad); } if (power != null) { if (NVML.NvmlDeviceGetPowerUsage(device.Value, out int powerValue) == NVML.NvmlReturn.Success) { power.Value = powerValue * 0.001f; ActivateSensor(power); } } if (pcieThroughputRx != null) { if (NVML.NvmlDeviceGetPcieThroughput(device.Value, NVML.NvmlPcieUtilCounter.RxBytes, out uint value) == NVML.NvmlReturn.Success) { pcieThroughputRx.Value = value * (1.0f / 0x400); ActivateSensor(pcieThroughputRx); } } if (pcieThroughputTx != null) { if (NVML.NvmlDeviceGetPcieThroughput(device.Value, NVML.NvmlPcieUtilCounter.TxBytes, out uint value) == NVML.NvmlReturn.Success) { pcieThroughputTx.Value = value * (1.0f / 0x400); ActivateSensor(pcieThroughputTx); } } }
/// <summary> /// Validates a set of GPU outputs to check if they can be active simultaneously /// </summary> /// <param name="outputs">GPU outputs to check</param> /// <returns>true if all specified outputs can be active simultaneously, otherwise false</returns> public bool ValidateOutputCombination(GPUOutput[] outputs) { var gpuOutpudIds = outputs.Aggregate(OutputId.Invalid, (current, gpuOutput) => current | gpuOutput.OutputId); return(GPUApi.ValidateOutputCombination(Handle, gpuOutpudIds)); }
/// <summary> /// Get a list of all display devices on any possible output /// </summary> /// <returns>An array of display devices</returns> public DisplayDevice[] GetDisplayDevices() { return(GPUApi.GetAllDisplayIds(Handle).Select(display => new DisplayDevice(display)).ToArray()); }
/// <summary> /// Get the display device connected to a specific GPU output /// </summary> /// <param name="output">The GPU output to get connected display device for</param> /// <returns>DisplayDevice connected to the specified GPU output</returns> public DisplayDevice GetDisplayDeviceByOutput(GPUOutput output) { return(new DisplayDevice(GPUApi.GetDisplayIdFromGPUAndOutputId(Handle, output.OutputId))); }
/// <summary> /// Get a list of all connected display devices on this GPU /// </summary> /// <param name="flags">ConnectedIdsFlag flag</param> /// <returns>An array of display devices</returns> public DisplayDevice[] GetConnectedDisplayDevices(ConnectedIdsFlag flags) { return(GPUApi.GetConnectedDisplayIds(Handle, flags).Select(display => new DisplayDevice(display)).ToArray()); }
/// <summary> /// Gets all physical GPUs in TCC state /// </summary> /// <returns>An array of physical GPUs</returns> public static PhysicalGPU[] GetTCCPhysicalGPUs() { return(GPUApi.EnumTCCPhysicalGPUs().Select(handle => new PhysicalGPU(handle)).ToArray()); }
private int GetCurrentPCIeLanes() { return(GPUApi.GetCurrentPCIEDownStreamWidth(PhysicalGPU.GetPhysicalGPUs()[0].Handle)); }
internal GPUOutput(OutputId outputId, PhysicalGPUHandle gpuHandle) { OutputId = outputId; OutputType = !gpuHandle.IsNull ? GPUApi.GetOutputType(gpuHandle, outputId) : OutputType.Unknown; PhysicalGPU = new PhysicalGPU(gpuHandle); }
/// <summary> /// Gets all logical GPUs /// </summary> /// <returns>An array of logical GPUs</returns> public static LogicalGPU[] GetLogicalGPUs() { return(GPUApi.EnumLogicalGPUs().Select(handle => new LogicalGPU(handle)).ToArray()); }
public override void Update() { NvGPUThermalSettings settings = GetThermalSettings(); foreach (Sensor sensor in temperatures) { sensor.Value = settings.Sensor[sensor.Index].CurrentTemp; } bool tachReadingOk = false; if (NVAPI.NvAPI_GPU_GetTachReading != null && NVAPI.NvAPI_GPU_GetTachReading(handle, out int fanValue) == NvStatus.OK) { fan.Value = fanValue; ActivateSensor(fan); tachReadingOk = true; } uint[] values = GetClocks(); if (values != null) { clocks[1].Value = 0.001f * values[8]; if (values[30] != 0) { clocks[0].Value = 0.0005f * values[30]; clocks[2].Value = 0.001f * values[30]; } else { clocks[0].Value = 0.001f * values[0]; clocks[2].Value = 0.001f * values[14]; } } // set extra sensors from external NvAPI wrapper if (physicalGPU != null) { try { voltage.Value = GPUApi.GetCurrentVoltage(physicalGPU.Handle).ValueInMicroVolt / 1E06f; ActivateSensor(voltage); var currentActiveLimit = physicalGPU.PerformanceControl.CurrentActiveLimit; powerLimit.Value = ((currentActiveLimit & PerformanceLimit.PowerLimit) == PerformanceLimit.PowerLimit) ? 1 : 0; ActivateSensor(powerLimit); temperatureLimit.Value = ((currentActiveLimit & PerformanceLimit.TemperatureLimit) == PerformanceLimit.TemperatureLimit) ? 1 : 0; ActivateSensor(temperatureLimit); voltageLimit.Value = ((currentActiveLimit & PerformanceLimit.VoltageLimit) == PerformanceLimit.VoltageLimit) ? 1 : 0; ActivateSensor(voltageLimit); } catch { voltage.Value = float.NaN; powerLimit.Value = float.NaN; temperatureLimit.Value = float.NaN; voltageLimit.Value = float.NaN; } } var infoEx = new NvDynamicPstatesInfoEx(); infoEx.Version = NVAPI.GPU_DYNAMIC_PSTATES_INFO_EX_VER; infoEx.UtilizationDomains = new NvUtilizationDomainEx[NVAPI.NVAPI_MAX_GPU_UTILIZATIONS]; if (NVAPI.NvAPI_GPU_GetDynamicPstatesInfoEx != null && NVAPI.NvAPI_GPU_GetDynamicPstatesInfoEx(handle, ref infoEx) == NvStatus.OK) { for (int i = 0; i < loads.Length; i++) { if (infoEx.UtilizationDomains[i].Present) { loads[i].Value = infoEx.UtilizationDomains[i].Percentage; ActivateSensor(loads[i]); } } } else { var info = new NvDynamicPstatesInfo { Version = NVAPI.GPU_DYNAMIC_PSTATES_INFO_VER, UtilizationDomains = new NvUtilizationDomain[NVAPI.NVAPI_MAX_GPU_UTILIZATIONS] }; if (NVAPI.NvAPI_GPU_GetDynamicPstatesInfo != null && NVAPI.NvAPI_GPU_GetDynamicPstatesInfo(handle, ref info) == NvStatus.OK) { for (int i = 0; i < loads.Length; i++) { if (info.UtilizationDomains[i].Present) { loads[i].Value = info.UtilizationDomains[i].Percentage; ActivateSensor(loads[i]); } } } } var coolerSettings = GetCoolerSettings(); var coolerSettingsOk = false; if (coolerSettings.Count > 0) { control.Value = coolerSettings.Cooler[0].CurrentLevel; ActivateSensor(control); coolerSettingsOk = true; } if (!tachReadingOk || !coolerSettingsOk) { var coolersStatus = GetFanCoolersStatus(); if (coolersStatus.Count > 0) { if (!coolerSettingsOk) { control.Value = coolersStatus.Items[0].CurrentLevel; ActivateSensor(control); coolerSettingsOk = true; } if (!tachReadingOk) { fan.Value = coolersStatus.Items[0].CurrentRpm; ActivateSensor(fan); tachReadingOk = true; } } } NvDisplayDriverMemoryInfo memoryInfo = new NvDisplayDriverMemoryInfo { Version = NVAPI.DISPLAY_DRIVER_MEMORY_INFO_VER, Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU] }; if (NVAPI.NvAPI_GetDisplayDriverMemoryInfo != null && displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverMemoryInfo(displayHandle.Value, ref memoryInfo) == NvStatus.OK) { uint totalMemory = memoryInfo.Values[0]; uint freeMemory = memoryInfo.Values[4]; float usedMemory = Math.Max(totalMemory - freeMemory, 0); memoryFree.Value = (float)freeMemory / 1024; memoryAvail.Value = (float)totalMemory / 1024; memoryUsed.Value = usedMemory / 1024; memoryLoad.Value = 100f * usedMemory / totalMemory; ActivateSensor(memoryAvail); ActivateSensor(memoryUsed); ActivateSensor(memoryFree); ActivateSensor(memoryLoad); } if (power != null) { var channels = new NvGpuPowerMonitorPowerChannelStatus[NVAPI.POWER_STATUS_CHANNEL_COUNT]; for (int i = 0; i < channels.Length; i++) { channels[i].Rsvd = new byte[NVAPI.POWER_STATUS_RSVD_SIZE]; } var powerStatus = new NvGpuPowerStatus { Version = NVAPI.GPU_POWER_MONITOR_STATUS_VER, Rsvd = new byte[NVAPI.POWER_STATUS_RSVD_SIZE], Channels = channels }; if (NVAPI.NvAPI_GPU_PowerMonitorGetStatus != null && NVAPI.NvAPI_GPU_PowerMonitorGetStatus(handle, ref powerStatus) == NvStatus.OK) { power.Value = powerStatus.TotalGpuPowermW * 1E-03f; ActivateSensor(power); //// Grap all other sensors/channels //var powerSensors = powerStatus.Channels.Where(ch => ch.PwrAvgmW != 0).Select(ch => ch.PwrAvgmW * 1E-03).ToArray(); //for (int i = 0; i < powerSensors.Length; i++) //{ // Console.WriteLine($"Sensor {i}: {powerSensors[i]}W"); //} //Console.WriteLine("------------------------------------------"); } } // update VRAM usage if (dedicatedVramUsagePerformCounter != null) { try { memoryUsageDedicated.Value = dedicatedVramUsagePerformCounter.NextValue() / 1024f / 1024f; ActivateSensor(memoryUsageDedicated); } catch { } } if (sharedVramUsagePerformCounter != null) { try { memoryUsageShared.Value = (float)sharedVramUsagePerformCounter.NextValue() / 1024f / 1024f; ActivateSensor(memoryUsageShared); } catch { } } if (pcieThroughputRx != null) { if (NVML.NvmlDeviceGetPcieThroughput(device.Value, NVML.NvmlPcieUtilCounter.RxBytes, out uint value) == NVML.NvmlReturn.Success) { pcieThroughputRx.Value = value / 1024f; ActivateSensor(pcieThroughputRx); } } if (pcieThroughputTx != null) { if (NVML.NvmlDeviceGetPcieThroughput(device.Value, NVML.NvmlPcieUtilCounter.TxBytes, out uint value) == NVML.NvmlReturn.Success) { pcieThroughputTx.Value = value / 1024f; ActivateSensor(pcieThroughputTx); } } }
public NvidiaGroup(ISettings settings) { if (!NVAPI.IsAvailable) { return; } report.AppendLine("NVAPI"); report.AppendLine(); if (NVAPI.NvAPI_GetInterfaceVersionString(out string version) == NvStatus.OK) { report.Append(" Version: "); report.AppendLine(version); } NvPhysicalGpuHandle[] handles = new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS]; int count; if (NVAPI.NvAPI_EnumPhysicalGPUs == null) { report.AppendLine(" Error: NvAPI_EnumPhysicalGPUs not available"); report.AppendLine(); return; } else { NvStatus status = NVAPI.NvAPI_EnumPhysicalGPUs(handles, out count); if (status != NvStatus.OK) { report.AppendLine(" Status: " + status); report.AppendLine(); return; } } var result = NVML.NvmlInit(); report.AppendLine(); report.AppendLine("NVML"); report.AppendLine(); report.AppendLine(" Status: " + result); report.AppendLine(); IDictionary <NvPhysicalGpuHandle, NvDisplayHandle> displayHandles = new Dictionary <NvPhysicalGpuHandle, NvDisplayHandle>(); if (NVAPI.NvAPI_EnumNvidiaDisplayHandle != null && NVAPI.NvAPI_GetPhysicalGPUsFromDisplay != null) { NvStatus status = NvStatus.OK; int i = 0; while (status == NvStatus.OK) { NvDisplayHandle displayHandle = new NvDisplayHandle(); status = NVAPI.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle); i++; if (status == NvStatus.OK) { NvPhysicalGpuHandle[] handlesFromDisplay = new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS]; uint countFromDisplay; if (NVAPI.NvAPI_GetPhysicalGPUsFromDisplay(displayHandle, handlesFromDisplay, out countFromDisplay) == NvStatus.OK) { for (int j = 0; j < countFromDisplay; j++) { if (!displayHandles.ContainsKey(handlesFromDisplay[j])) { displayHandles.Add(handlesFromDisplay[j], displayHandle); } } } } } } report.Append("Number of GPUs: "); report.AppendLine(count.ToString(CultureInfo.InvariantCulture)); // API wrapper calls PhysicalGPUHandle[] physicalGPUHandles = null; try { physicalGPUHandles = GPUApi.EnumPhysicalGPUs(); } catch { } for (int i = 0; i < count; i++) { displayHandles.TryGetValue(handles[i], out NvDisplayHandle displayHandle); if (physicalGPUHandles == null || !physicalGPUHandles.Any()) { hardware.Add(new NvidiaGPU(i, handles[i], displayHandle, settings)); } else { hardware.Add(new NvidiaGPU(i, handles[i], displayHandle, settings, new NvAPIWrapper.GPU.PhysicalGPU(physicalGPUHandles[i]))); } } report.AppendLine(); }