diff --git a/LibreHardwareMonitorLib/Hardware/D3DDisplayDevice.cs b/LibreHardwareMonitorLib/Hardware/D3DDisplayDevice.cs index 3c0ec39..4fe02b9 100644 --- a/LibreHardwareMonitorLib/Hardware/D3DDisplayDevice.cs +++ b/LibreHardwareMonitorLib/Hardware/D3DDisplayDevice.cs @@ -99,6 +99,7 @@ internal static class D3DDisplayDevice return false; deviceInfo.GpuSharedLimit = segmentSizeInfo.SharedSystemMemorySize; + deviceInfo.GpuVideoMemoryLimit = segmentSizeInfo.DedicatedVideoMemorySize; deviceInfo.GpuDedicatedLimit = segmentSizeInfo.DedicatedSystemMemorySize; for (uint segmentId = 0; segmentId < segmentCount; segmentId++) @@ -273,6 +274,7 @@ internal static class D3DDisplayDevice { public ulong GpuSharedLimit; public ulong GpuDedicatedLimit; + public ulong GpuVideoMemoryLimit; public ulong GpuSharedUsed; public ulong GpuDedicatedUsed; diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs index 659c950..a7a6f42 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs @@ -32,13 +32,20 @@ internal sealed class AmdGpu : GenericGpu private readonly bool _frameMetricsStarted; private readonly Sensor _fullscreenFps; private readonly Sensor _gpuDedicatedMemoryUsage; + private readonly Sensor _gpuDedicatedMemoryFree; + private readonly Sensor _gpuDedicatedMemoryTotal; private readonly Sensor[] _gpuNodeUsage; private readonly DateTime[] _gpuNodeUsagePrevTick; private readonly long[] _gpuNodeUsagePrevValue; private readonly Sensor _gpuSharedMemoryUsage; + private readonly Sensor _gpuSharedMemoryFree; + private readonly Sensor _gpuSharedMemoryTotal; private readonly Sensor _memoryClock; private readonly Sensor _memoryLoad; private readonly Sensor _memoryVoltage; + private readonly Sensor _memoryTotal; + private readonly Sensor _memoryUsed; + private readonly Sensor _memoryFree; private readonly bool _overdriveApiSupported; private readonly bool _pmLogStarted; private readonly Sensor _powerCore; @@ -98,6 +105,10 @@ internal sealed class AmdGpu : GenericGpu _fullscreenFps = new Sensor("Fullscreen FPS", 0, SensorType.Factor, this, settings); + _memoryUsed = new Sensor("GPU Memory Used", 0, SensorType.SmallData, this, settings); + _memoryFree = new Sensor("GPU Memory Free", 1, SensorType.SmallData, this, settings); + _memoryTotal = new Sensor("GPU Memory Total", 2, SensorType.SmallData, this, settings); + if (!Software.OperatingSystem.IsUnix) { string[] deviceIds = D3DDisplayDevice.GetDeviceIdentifiers(); @@ -114,10 +125,14 @@ internal sealed class AmdGpu : GenericGpu _d3dDeviceId = deviceId; int nodeSensorIndex = 2; - int memorySensorIndex = 0; + int memorySensorIndex = 3; _gpuDedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", memorySensorIndex++, SensorType.SmallData, this, settings); - _gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", memorySensorIndex, SensorType.SmallData, this, settings); + _gpuDedicatedMemoryFree = new Sensor("D3D Dedicated Memory Free", memorySensorIndex++, SensorType.SmallData, this, settings); + _gpuDedicatedMemoryTotal = new Sensor("D3D Dedicated Memory Total", memorySensorIndex++, SensorType.SmallData, this, settings); + _gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", memorySensorIndex++, SensorType.SmallData, this, settings); + _gpuSharedMemoryFree = new Sensor("D3D Shared Memory Free", memorySensorIndex++, SensorType.SmallData, this, settings); + _gpuSharedMemoryTotal = new Sensor("D3D Shared Memory Total", memorySensorIndex++, SensorType.SmallData, this, settings); _gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length]; _gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length]; @@ -136,6 +151,14 @@ internal sealed class AmdGpu : GenericGpu } } + AtiAdlxx.ADLMemoryInfoX4 memoryInfo = new(); + if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_MemoryInfoX4_Get)) && + AtiAdlxx.ADL2_Adapter_MemoryInfoX4_Get(_context, _adapterInfo.AdapterIndex, out memoryInfo) == AtiAdlxx.ADLStatus.ADL_OK) + { + _memoryTotal.Value = memoryInfo.iMemorySize / 1024 / 1024; + ActivateSensor(_memoryTotal); + } + int supported = 0; int enabled = 0; int version = 0; @@ -291,10 +314,18 @@ internal sealed class AmdGpu : GenericGpu { if (_d3dDeviceId != null && D3DDisplayDevice.GetDeviceInfoByIdentifier(_d3dDeviceId, out D3DDisplayDevice.D3DDeviceInfo deviceInfo)) { + _gpuDedicatedMemoryTotal.Value = 1f * deviceInfo.GpuVideoMemoryLimit / 1024 / 1024; _gpuDedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024; + _gpuDedicatedMemoryFree.Value = _gpuDedicatedMemoryTotal.Value - _gpuDedicatedMemoryUsage.Value; _gpuSharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024; + _gpuSharedMemoryTotal.Value = 1f * deviceInfo.GpuSharedLimit / 1024 / 1024; + _gpuSharedMemoryFree.Value = _gpuSharedMemoryTotal.Value - _gpuSharedMemoryUsage.Value; + ActivateSensor(_gpuDedicatedMemoryTotal); + ActivateSensor(_gpuDedicatedMemoryFree); ActivateSensor(_gpuDedicatedMemoryUsage); ActivateSensor(_gpuSharedMemoryUsage); + ActivateSensor(_gpuSharedMemoryFree); + ActivateSensor(_gpuSharedMemoryTotal); foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes) { @@ -308,6 +339,20 @@ internal sealed class AmdGpu : GenericGpu } } + int vramUsed = 0; + if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_DedicatedVRAMUsage_Get)) && + AtiAdlxx.ADL2_Adapter_DedicatedVRAMUsage_Get(_context, _adapterInfo.AdapterIndex, out vramUsed) == AtiAdlxx.ADLStatus.ADL_OK) + { + _memoryUsed.Value = vramUsed; + ActivateSensor(_memoryUsed); + } + + if (_memoryTotal.Value > 0) + { + _memoryFree.Value = _memoryTotal.Value - _memoryUsed.Value; + ActivateSensor(_memoryFree); + } + if (_frameMetricsStarted) { float framesPerSecond = 0; diff --git a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs index adead65..a557554 100644 --- a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs +++ b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs @@ -170,6 +170,14 @@ internal static class AtiAdlxx [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] public static extern ADLStatus ADL2_Adapter_Active_Get(IntPtr context, int adapterIndex, out int status); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + public static extern ADLStatus ADL2_Adapter_DedicatedVRAMUsage_Get(IntPtr context, int adapterIndex, out int iVRAMUsageInMB); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + public static extern ADLStatus ADL2_Adapter_MemoryInfoX4_Get(IntPtr context, int adapterIndex, out ADLMemoryInfoX4 memoryInfo); + public static bool ADL_Method_Exists(string ADL_Method) { IntPtr module = Kernel32.LoadLibrary(DllName); @@ -690,4 +698,28 @@ internal static class AtiAdlxx public int ASICFamilyId; public int ASICRevisionId; } + + [StructLayout(LayoutKind.Sequential)] + internal struct ADLMemoryInfoX4 + { + /// Memory size in bytes. + public long iMemorySize; + /// Memory type in string. + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = ADL_MAX_PATH)] + public string strMemoryType; + /// Highest default performance level Memory bandwidth in Mbytes/s + public long iMemoryBandwidth; + /// HyperMemory size in bytes. + public long iHyperMemorySize; + /// Invisible Memory size in bytes. + public long iInvisibleMemorySize; + /// Visible Memory size in bytes. + public long iVisibleMemorySize; + /// Vram vendor ID + public long iVramVendorRevId; + /// Memory Bandiwidth that is calculated and finalized on the driver side, grab and go. + public long iMemoryBandwidthX2; + /// Memory Bit Rate that is calculated and finalized on the driver side, grab and go. + public long iMemoryBitRateX2; + } }