mirror of
https://github.com/RPCS3/discord-bot.git
synced 2025-04-14 02:40:44 +00:00
170 lines
6.9 KiB
C#
170 lines
6.9 KiB
C#
using System.Net.Http;
|
|
using System.Xml.Linq;
|
|
using CompatApiClient.Compression;
|
|
|
|
namespace CompatBot.Database.Providers;
|
|
|
|
internal static class AmdDriverVersionProvider
|
|
{
|
|
private static readonly Dictionary<string, List<string>> VulkanToDriver = new();
|
|
private static readonly Dictionary<string, string> OpenglToDriver = new();
|
|
private static readonly Dictionary<string, string> InternalToDriver = new();
|
|
private static readonly SemaphoreSlim SyncObj = new(1, 1);
|
|
|
|
public static async Task RefreshAsync()
|
|
{
|
|
if (await SyncObj.WaitAsync(0).ConfigureAwait(false))
|
|
try
|
|
{
|
|
using var httpClient = HttpClientFactory.Create(new CompressionMessageHandler());
|
|
await using var response = await httpClient.GetStreamAsync("https://raw.githubusercontent.com/GPUOpen-Drivers/amd-vulkan-versions/master/amdversions.xml").ConfigureAwait(false);
|
|
var xml = await XDocument.LoadAsync(response, LoadOptions.None, Config.Cts.Token).ConfigureAwait(false);
|
|
if (xml.Root is null)
|
|
{
|
|
Config.Log.Warn("Failed to update AMD version mapping");
|
|
return;
|
|
}
|
|
|
|
foreach (var driver in xml.Root.Elements("driver"))
|
|
{
|
|
var winVer = (string?)driver.Element("windows-version");
|
|
var vkVer = (string?)driver.Element("vulkan-version");
|
|
var internVer = (string?)driver.Element("internal-version");
|
|
var driverVer = (string?)driver.Attribute("version");
|
|
if (vkVer is null)
|
|
continue;
|
|
|
|
if (!VulkanToDriver.TryGetValue(vkVer, out var verList))
|
|
VulkanToDriver[vkVer] = verList = new();
|
|
if (string.IsNullOrEmpty(driverVer))
|
|
continue;
|
|
|
|
verList.Insert(0, driverVer);
|
|
if (!string.IsNullOrEmpty(winVer))
|
|
OpenglToDriver[winVer] = driverVer;
|
|
if (!string.IsNullOrEmpty(internVer))
|
|
InternalToDriver[internVer] = driverVer;
|
|
}
|
|
foreach (var key in VulkanToDriver.Keys.ToList())
|
|
VulkanToDriver[key] = VulkanToDriver[key].Distinct().ToList();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Config.Log.Warn(e, "Failed to update AMD version mapping");
|
|
}
|
|
finally
|
|
{
|
|
SyncObj.Release();
|
|
}
|
|
}
|
|
|
|
public static async ValueTask<string> GetFromOpenglAsync(string openglVersion, bool autoRefresh = true)
|
|
{
|
|
if (OpenglToDriver.TryGetValue(openglVersion, out var result))
|
|
return result;
|
|
|
|
if (!Version.TryParse(openglVersion, out var glVersion))
|
|
return openglVersion;
|
|
|
|
if (glVersion is { Major: >= 22, Minor: < 13, Build: <10, Revision: > 220600 })
|
|
return $"{glVersion.Major}.{glVersion.Minor}.{glVersion.Build}";
|
|
|
|
var glVersions = new List<(Version glVer, string driverVer)>(OpenglToDriver.Count);
|
|
foreach (var key in OpenglToDriver.Keys)
|
|
{
|
|
if (Version.TryParse(key, out var ver))
|
|
glVersions.Add((ver, OpenglToDriver[key]));
|
|
}
|
|
if (glVersions.Count == 0)
|
|
return openglVersion;
|
|
|
|
glVersions.Sort((l, r) => l.glVer < r.glVer ? -1 : l.glVer > r.glVer ? 1 : 0);
|
|
if (glVersion < glVersions[0].glVer)
|
|
return $"older than {glVersions[0].driverVer} ({openglVersion})";
|
|
|
|
var newest = glVersions.Last();
|
|
if (glVersion > newest.glVer)
|
|
{
|
|
if (autoRefresh)
|
|
{
|
|
await RefreshAsync().ConfigureAwait(false);
|
|
return await GetFromOpenglAsync(openglVersion, false).ConfigureAwait(false);
|
|
}
|
|
|
|
return $"newer than {newest.driverVer} ({openglVersion})";
|
|
}
|
|
|
|
var approximate = glVersions.FirstOrDefault(v => v.glVer.Minor == glVersion.Minor && v.glVer.Build == glVersion.Build);
|
|
if (!string.IsNullOrEmpty(approximate.driverVer))
|
|
return $"{approximate.driverVer} rev {glVersion.Revision}";
|
|
|
|
if (string.IsNullOrEmpty(approximate.driverVer))
|
|
for (var i = 0; i < glVersions.Count - 1; i++)
|
|
if (glVersion > glVersions[i].glVer && glVersion < glVersions[i + 1].glVer)
|
|
{
|
|
approximate = glVersions[i];
|
|
break;
|
|
}
|
|
if (!string.IsNullOrEmpty(approximate.driverVer))
|
|
return $"probably {approximate.driverVer}";
|
|
|
|
return openglVersion;
|
|
}
|
|
|
|
public static async ValueTask<string> GetFromVulkanAsync(string vulkanVersion, bool autoRefresh = true)
|
|
{
|
|
if (!VulkanToDriver.TryGetValue(vulkanVersion, out var result))
|
|
await RefreshAsync().ConfigureAwait(false);
|
|
|
|
if (result?.Count > 0 || (VulkanToDriver.TryGetValue(vulkanVersion, out result) && result.Count > 0))
|
|
{
|
|
if (result.Count == 1)
|
|
return result[0];
|
|
return $"{result.First()} - {result.Last()}";
|
|
}
|
|
|
|
if (Version.TryParse(vulkanVersion, out var vkVer))
|
|
{
|
|
var vkVersions = new List<(Version vkVer, List<string> driverVers)>(VulkanToDriver.Count);
|
|
foreach (var key in VulkanToDriver.Keys)
|
|
{
|
|
if (Version.TryParse(key, out var ver))
|
|
vkVersions.Add((ver, VulkanToDriver[key]));
|
|
}
|
|
if (vkVersions.Count == 0)
|
|
return vulkanVersion;
|
|
|
|
vkVersions.Sort((l, r) => l.vkVer < r.vkVer ? -1 : l.vkVer > r.vkVer ? 1 : 0);
|
|
if (vkVer < vkVersions[0].vkVer)
|
|
return $"older than {vkVersions[0].driverVers.First()} ({vulkanVersion})";
|
|
|
|
var (version, driverVers) = vkVersions.Last();
|
|
if (vkVer > version)
|
|
{
|
|
if (!autoRefresh)
|
|
return $"newer than {driverVers.Last()} ({vulkanVersion})";
|
|
|
|
await RefreshAsync().ConfigureAwait(false);
|
|
return await GetFromVulkanAsync(vulkanVersion, false).ConfigureAwait(false);
|
|
}
|
|
|
|
for (var i = 1; i < vkVersions.Count; i++)
|
|
{
|
|
if (vkVer >= vkVersions[i].vkVer)
|
|
continue;
|
|
|
|
var lowerVer = vkVersions[i - 1].vkVer;
|
|
var mapKey = VulkanToDriver.Keys.FirstOrDefault(k => Version.Parse(k) == lowerVer);
|
|
if (mapKey is null)
|
|
continue;
|
|
|
|
if (!VulkanToDriver.TryGetValue(mapKey, out var oldestDriverList))
|
|
continue;
|
|
|
|
return $"unknown version between {oldestDriverList.First()} and {vkVersions[i].driverVers.Last()} ({vulkanVersion})";
|
|
}
|
|
}
|
|
|
|
return vulkanVersion;
|
|
}
|
|
} |