From db4799e7abbc09b1e6bb1295ed23a217ce558b4e Mon Sep 17 00:00:00 2001 From: Babib3l Date: Mon, 17 Aug 2026 21:25:32 -0500 Subject: [PATCH] feature: Add GpuDriverVersion to GPU info logging - The Vulkan backend now reports the driver name and version using VK_KHR_driver_properties when available, with fallbacks for raw Vulkan driverVersion parsing. Intel Windows drivers also get the full package-style version from the driver UUID when exposed by the driver. OpenGL now carries its existing OpenGL version string through HardwareInfo.GpuDriverVersion. --- src/Ryujinx.Graphics.GAL/HardwareInfo.cs | 4 +- src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs | 2 +- src/Ryujinx.Graphics.Vulkan/Vendor.cs | 3 + src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 65 ++++++++++++++++++- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx.Graphics.GAL/HardwareInfo.cs b/src/Ryujinx.Graphics.GAL/HardwareInfo.cs index c2546fa46..2ecbbc36c 100644 --- a/src/Ryujinx.Graphics.GAL/HardwareInfo.cs +++ b/src/Ryujinx.Graphics.GAL/HardwareInfo.cs @@ -5,12 +5,14 @@ namespace Ryujinx.Graphics.GAL public string GpuVendor { get; } public string GpuModel { get; } public string GpuDriver { get; } + public string GpuDriverVersion { get; } - public HardwareInfo(string gpuVendor, string gpuModel, string gpuDriver) + public HardwareInfo(string gpuVendor, string gpuModel, string gpuDriver, string gpuDriverVersion) { GpuVendor = gpuVendor; GpuModel = gpuModel; GpuDriver = gpuDriver; + GpuDriverVersion = gpuDriverVersion; } } } diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 05e1eee49..ad5847a29 100644 --- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.OpenGL public HardwareInfo GetHardwareInfo() { - return new HardwareInfo(GpuVendor, GpuRenderer, GpuVendor); // OpenGL does not provide a driver name, vendor name is closest analogue. + return new HardwareInfo(GpuVendor, GpuRenderer, GpuVendor, GpuVersion); // OpenGL does not provide a driver name, vendor name is closest analogue. } public PinnedSpan GetBufferData(BufferHandle buffer, int offset, int size) diff --git a/src/Ryujinx.Graphics.Vulkan/Vendor.cs b/src/Ryujinx.Graphics.Vulkan/Vendor.cs index 423f07e80..7863a6b67 100644 --- a/src/Ryujinx.Graphics.Vulkan/Vendor.cs +++ b/src/Ryujinx.Graphics.Vulkan/Vendor.cs @@ -36,6 +36,9 @@ namespace Ryujinx.Graphics.Vulkan [GeneratedRegex(@"Adreno (\(TM\) )?(8[0-9]\d)")] public static partial Regex Adreno8xxRegex(); + [GeneratedRegex(@"^\d+\.\d+\.\d+\.\d+$")] + internal static partial Regex IntelWindowsDriverVersionRegex(); + public static Vendor FromId(uint id) { return id switch diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index ad8f86160..c87ed6658 100644 --- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -115,6 +115,7 @@ namespace Ryujinx.Graphics.Vulkan public string GpuDriver { get; private set; } public string GpuRenderer { get; private set; } public string GpuVersion { get; private set; } + public string GpuDriverVersion { get; private set; } public bool PreferThreading => true; @@ -185,6 +186,14 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDeviceProperties2, }; + PhysicalDeviceIDProperties propertiesId = new() + { + SType = StructureType.PhysicalDeviceIDProperties, + PNext = properties2.PNext, + }; + + properties2.PNext = &propertiesId; + PhysicalDeviceSubgroupProperties propertiesSubgroup = new() { SType = StructureType.PhysicalDeviceSubgroupProperties, @@ -374,13 +383,17 @@ namespace Ryujinx.Graphics.Vulkan GpuVendor = VendorUtils.GetNameFromId(properties.VendorID); GpuDriver = hasDriverProperties && !OperatingSystem.IsMacOS() ? VendorUtils.GetFriendlyDriverName(driverProperties.DriverID) : GpuVendor; // Fallback to vendor name if driver is unavailable or on MacOS where vendor is preferred. + GpuDriverVersion = TryGetIntelWindowsDriverVersionFromUuid(ref propertiesId, out string intelDriverVersion) ? intelDriverVersion : + hasDriverProperties ? + GetDriverInfo(ref driverProperties) ?? ParseDriverVersion(ref properties) : + ParseDriverVersion(ref properties); fixed (byte* deviceName = properties.DeviceName) { GpuRenderer = Marshal.PtrToStringAnsi((nint)deviceName); } - GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}"; + GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}"; IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && VendorUtils.AmdGcnRegex().IsMatch(GpuRenderer); @@ -846,7 +859,7 @@ namespace Ryujinx.Graphics.Vulkan public HardwareInfo GetHardwareInfo() { - return new HardwareInfo(GpuVendor, GpuRenderer, GpuDriver); + return new HardwareInfo(GpuVendor, GpuRenderer, GpuDriver, GpuDriverVersion); } /// @@ -896,9 +909,55 @@ namespace Ryujinx.Graphics.Vulkan return $"{(driverVersionRaw >> 22) & 0x3FF}.{(driverVersionRaw >> 14) & 0xFF}.{(driverVersionRaw >> 6) & 0xFF}.{driverVersionRaw & 0x3F}"; } + // Intel's Windows Vulkan driver exposes the 101.xxxx build portion in a custom layout. + if (properties.VendorID == 0x8086 && OperatingSystem.IsWindows()) + { + return $"{driverVersionRaw >> 14}.{driverVersionRaw & 0x3FFF}"; + } + return ParseStandardVulkanVersion(driverVersionRaw); } + private static unsafe string GetDriverInfo(ref PhysicalDeviceDriverPropertiesKHR driverProperties) + { + fixed (byte* driverInfo = driverProperties.DriverInfo) + { + string driverInfoString = Marshal.PtrToStringAnsi((nint)driverInfo); + + return string.IsNullOrWhiteSpace(driverInfoString) ? null : driverInfoString; + } + } + + private static unsafe bool TryGetIntelWindowsDriverVersionFromUuid(ref PhysicalDeviceIDProperties propertiesId, out string driverVersion) + { + driverVersion = null; + + if (!OperatingSystem.IsWindows()) + { + return false; + } + + fixed (byte* driverUuid = propertiesId.DriverUuid) + { + string driverUuidString = Marshal.PtrToStringAnsi((nint)driverUuid, (int)Vk.UuidSize); + int terminatorIndex = driverUuidString.IndexOf('\0'); + + if (terminatorIndex >= 0) + { + driverUuidString = driverUuidString[..terminatorIndex]; + } + + if (VendorUtils.IntelWindowsDriverVersionRegex().IsMatch(driverUuidString)) + { + driverVersion = driverUuidString; + + return true; + } + } + + return false; + } + internal PrimitiveTopology TopologyRemap(PrimitiveTopology topology) { return topology switch @@ -924,7 +983,7 @@ namespace Ryujinx.Graphics.Vulkan private void PrintGpuInformation() { - Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})"); + Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion}, Driver: {GpuDriver} {GpuDriverVersion})"); Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB"); }