Last active
May 22, 2020 05:14
-
-
Save davidfoster/0ad08b490676e548c593dfdade3b725f to your computer and use it in GitHub Desktop.
GPU Detection and Auto Quality Designation in Unity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Text.RegularExpressions; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
[InitializeOnLoad] | |
#endif | |
public static class GpuDetection { | |
// N.B. type definitions are ordered above constants in this class because it makes more sense that way in this case. | |
//----------------------------------------------------------------------------------------- | |
// Type Definitions: | |
//----------------------------------------------------------------------------------------- | |
public enum Vendors { | |
Unknown, | |
Nvidia, | |
Amd | |
} | |
public enum Gpus { | |
Unknown, | |
NvidiaUnknown, | |
// Maxwell. | |
NvidiaGtx780, // #42, http://gpu.userbenchmark.com/Nvidia-GTX-780/Rating/2164 | |
NvidiaGtx780M, // #83, http://gpu.userbenchmark.com/SpeedTest/7760/NVIDIA-GeForce-GTX-780M | |
NvidiaGtx780Ti, // #28, http://gpu.userbenchmark.com/Nvidia-GTX-780-Ti/Rating/2165 | |
NvidiaGtx960, // #63, http://gpu.userbenchmark.com/Nvidia-GTX-960/Rating/3165 | |
NvidiaGtx960M, // #128, http://gpu.userbenchmark.com/SpeedTest/27242/NVIDIA-GeForce-GTX-960M | |
NvidiaGtx965M, // #93, http://gpu.userbenchmark.com/SpeedTest/24481/NVIDIA-GeForce-GTX-965M | |
NvidiaGtx970, // #38, http://gpu.userbenchmark.com/Nvidia-GTX-970/Rating/2577 | |
NvidiaGtx970M, // #67, http://gpu.userbenchmark.com/SpeedTest/17319/NVIDIA-GeForce-GTX-970M | |
NvidiaGtx980, // #26, http://gpu.userbenchmark.com/Nvidia-GTX-980/Rating/2576 | |
NvidiaGtx980M, // #50, http://gpu.userbenchmark.com/SpeedTest/15596/NVIDIA-GeForce-GTX-980M | |
NvidiaGtx980Ti, // #16, http://gpu.userbenchmark.com/Nvidia-GTX-980-Ti/Rating/3439 | |
NvidiaGtxTitan, // #41, http://gpu.userbenchmark.com/Nvidia-GTX-Titan/Rating/2191 | |
NvidiaGtxTitanLe, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
NvidiaGtxTitanBlack, // #31, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-Black/Rating/3158 | |
NvidiaGtxTitanX, // #17, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-X/Rating/3282 | |
NvidiaGtxTitanZ, // #33, http://gpu.userbenchmark.com/SpeedTest/17751/NVIDIA-GeForce-GTX-TITAN-Z | |
// Pascal. | |
NvidiaGtx1030, // #136, http://gpu.userbenchmark.com/SpeedTest/283726/NVIDIA-GeForce-GT-1030 | |
NvidiaGtx1050, // #78, http://gpu.userbenchmark.com/Nvidia-GTX-1050/Rating/3650 | |
NvidiaGtx10503Gb, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
NvidiaGtx1050M, // #86, http://gpu.userbenchmark.com/SpeedTest/211022/NVIDIA-GeForce-GTX-1050 | |
NvidiaGtx1050Ti, // #66, http://gpu.userbenchmark.com/Nvidia-GTX-1050-Ti/Rating/3649 | |
NvidiaGtx1050TiM, // #72, http://gpu.userbenchmark.com/SpeedTest/223242/NVIDIA-GeForce-GTX-1050-Ti | |
NvidiaGtx1060, // #27, http://gpu.userbenchmark.com/Nvidia-GTX-1060-6GB/Rating/3639 | |
NvidiaGtx10603Gb, // #35, http://gpu.userbenchmark.com/Nvidia-GTX-1060-3GB/Rating/3646 | |
NvidiaGtx10605Gb, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
NvidiaGtx1060M, // #45, http://gpu.userbenchmark.com/SpeedTest/164336/NVIDIA-GeForce-GTX-1060 | |
NvidiaGtx1070, // #15, http://gpu.userbenchmark.com/Nvidia-GTX-1070/Rating/3609 | |
NvidiaGtx1070M, // #21, http://gpu.userbenchmark.com/SpeedTest/164129/NVIDIA-GeForce-GTX-1070 | |
NvidiaGtx1070Ti, // #11, http://gpu.userbenchmark.com/Nvidia-GTX-1070-Ti/Rating/3943 | |
NvidiaGtx1080, // #8, http://gpu.userbenchmark.com/Nvidia-GTX-1080/Rating/3603 | |
NvidiaGtx1080M, // #14, http://gpu.userbenchmark.com/SpeedTest/165564/NVIDIA-GeForce-GTX-1080 | |
NvidiaGtx1080Ti, // #3, http://gpu.userbenchmark.com/Nvidia-GTX-1080-Ti/Rating/3918 | |
NvidiaTitanX, // #5, http://gpu.userbenchmark.com/SpeedTest/158352/NVIDIA-TITAN-X-Pascal | |
NvidiaTitanXp, // #2, http://gpu.userbenchmark.com/SpeedTest/265423/NVIDIA-TITAN-Xp | |
NvidiaTitanV, // #1, http://gpu.userbenchmark.com/SpeedTest/395529/NVIDIA-TITAN-V | |
// Turing. | |
NvidiaGtx1180, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
AmdUnknown, | |
// N.B. frustratingly AMD GPUs share PCI IDs, so we need to group them before teasing them apart. | |
AmdUnknownR9290Or390, // 0x67b1, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdUnknownR9290XOr390X, // 0x67b0, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdUnknownRx470Or480Or570Or580, // 0x67df, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdUnknownRx550Or560, // 0x67ff, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdUnknownR9FuryOrFuryXOrNano, // 0x7300, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdUnknownRxVega56Or64Or64Lc, // 0x687f, https://pci-ids.ucw.cz/read/PC/1002 | |
AmdR9290, // #40, http://gpu.userbenchmark.com/AMD-R9-290/Rating/2171 | |
AmdR9290X, // #32, http://gpu.userbenchmark.com/AMD-R9-290X/Rating/2166 | |
AmdR9390, // #37, http://gpu.userbenchmark.com/AMD-R9-390/Rating/3481 | |
AmdR9390X, // #29, http://gpu.userbenchmark.com/AMD-R9-390X/Rating/3497 | |
AmdRx460, // #95, http://gpu.userbenchmark.com/AMD-RX-460/Rating/3641 | |
AmdRx470, // #47, http://gpu.userbenchmark.com/AMD-RX-470/Rating/3640 | |
AmdRx480, // #39, http://gpu.userbenchmark.com/AMD-RX-480/Rating/3634 | |
AmdRx550, // #121, http://gpu.userbenchmark.com/AMD-RX-550/Rating/3925 | |
AmdRx560, // #82, http://gpu.userbenchmark.com/AMD-RX-560/Rating/3926 | |
AmdRx570, // #44, http://gpu.userbenchmark.com/AMD-RX-570/Rating/3924 | |
AmdRx580, // #30, http://gpu.userbenchmark.com/AMD-RX-580/Rating/3923 | |
AmdR9Nano, // #28, http://gpu.userbenchmark.com/SpeedTest/58413/AMD-Radeon-TM-R9-Fury | |
AmdR9Fury, // #24, http://gpu.userbenchmark.com/AMD-R9-Fury/Rating/3509 | |
AmdR9FuryX, // #23, http://gpu.userbenchmark.com/AMD-R9-Fury-X/Rating/3498 | |
AmdRxVegaMGl, // #73, http://gpu.userbenchmark.com/SpeedTest/453719/Radeon-RX-Vega-M-GL-Graphics | |
AmdRxVegaMGh, // #49, http://gpu.userbenchmark.com/SpeedTest/422266/Radeon-RX-Vega-M-GH-Graphics | |
AmdRxVega56, // #13, http://gpu.userbenchmark.com/AMD-RX-Vega-56/Rating/3938 | |
AmdRxVegaFe, // #12, http://gpu.userbenchmark.com/AMD-Vega-Frontier-Edition/Rating/3929 | |
AmdRxVega64, // #10, http://gpu.userbenchmark.com/AMD-RX-Vega-64/Rating/3933 | |
AmdRxVega64Lc // #7, http://gpu.userbenchmark.com/SpeedTest/353890/Radeon-RX-Vega | |
} | |
//----------------------------------------------------------------------------------------- | |
// Constants: | |
//----------------------------------------------------------------------------------------- | |
private static readonly Dictionary<int, Vendors> VENDOR_IDS = new Dictionary<int, Vendors> { | |
{ 0x10de, Vendors.Nvidia }, | |
{ 0x1002, Vendors.Amd }, | |
}; | |
// N.B. it is possible for the same device ID to be used by multiple vendors for different devices, so we must maintain each vendor's device IDs separately. | |
/// <remarks>List of NVIDIA PCI IDs: https://pci-ids.ucw.cz/read/PC/10de </remarks> | |
private static readonly Dictionary<int, Gpus> NVIDIA_GPU_IDS = new Dictionary<int, Gpus> { | |
{ 0xffff, Gpus.NvidiaUnknown }, | |
// Maxwell. | |
{ 0x1004, Gpus.NvidiaGtx780 }, // #42, http://gpu.userbenchmark.com/Nvidia-GTX-780/Rating/2164 | |
{ 0x1007, Gpus.NvidiaGtx780 }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x119e, Gpus.NvidiaGtx780M }, // #83, http://gpu.userbenchmark.com/SpeedTest/7760/NVIDIA-GeForce-GTX-780M | |
{ 0x119f, Gpus.NvidiaGtx780M }, // ^^ | |
{ 0x100a, Gpus.NvidiaGtx780Ti }, // #28, http://gpu.userbenchmark.com/Nvidia-GTX-780-Ti/Rating/2165 | |
{ 0x1008, Gpus.NvidiaGtx780Ti }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1401, Gpus.NvidiaGtx960 }, // #63, http://gpu.userbenchmark.com/Nvidia-GTX-960/Rating/3165 | |
{ 0x1406, Gpus.NvidiaGtx960 }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x139b, Gpus.NvidiaGtx960M }, // #128, http://gpu.userbenchmark.com/SpeedTest/27242/NVIDIA-GeForce-GTX-960M | |
{ 0x13d9, Gpus.NvidiaGtx965M }, // #93, http://gpu.userbenchmark.com/SpeedTest/24481/NVIDIA-GeForce-GTX-965M | |
{ 0x1427, Gpus.NvidiaGtx965M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1619, Gpus.NvidiaGtx965M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1667, Gpus.NvidiaGtx965M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x13c2, Gpus.NvidiaGtx970 }, // #38, http://gpu.userbenchmark.com/Nvidia-GTX-970/Rating/2577 | |
{ 0x13d8, Gpus.NvidiaGtx970M }, // #67, http://gpu.userbenchmark.com/SpeedTest/17319/NVIDIA-GeForce-GTX-970M | |
{ 0x1618, Gpus.NvidiaGtx970M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x13c0, Gpus.NvidiaGtx980 }, // #26, http://gpu.userbenchmark.com/Nvidia-GTX-980/Rating/2576 | |
{ 0x13e7, Gpus.NvidiaGtx980 }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x13d7, Gpus.NvidiaGtx980M }, // #50, http://gpu.userbenchmark.com/SpeedTest/15596/NVIDIA-GeForce-GTX-980M | |
{ 0x13da, Gpus.NvidiaGtx980M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1617, Gpus.NvidiaGtx980M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x161a, Gpus.NvidiaGtx980M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x17c8, Gpus.NvidiaGtx980Ti }, // #16, http://gpu.userbenchmark.com/Nvidia-GTX-980-Ti/Rating/3439 | |
{ 0x1005, Gpus.NvidiaGtxTitan }, // #41, http://gpu.userbenchmark.com/Nvidia-GTX-Titan/Rating/2191 | |
{ 0x1003, Gpus.NvidiaGtxTitanLe }, // ? https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x100c, Gpus.NvidiaGtxTitanBlack }, // #31, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-Black/Rating/3158 | |
{ 0x17c2, Gpus.NvidiaGtxTitanX }, // #17, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-X/Rating/3282 | |
{ 0x1001, Gpus.NvidiaGtxTitanZ }, // #33, http://gpu.userbenchmark.com/SpeedTest/17751/NVIDIA-GeForce-GTX-TITAN-Z | |
// Pascal. | |
{ 0x1d01, Gpus.NvidiaGtx1030 }, // #136, http://gpu.userbenchmark.com/SpeedTest/283726/NVIDIA-GeForce-GT-1030 | |
{ 0x1c81, Gpus.NvidiaGtx1050 }, // #78, http://gpu.userbenchmark.com/Nvidia-GTX-1050/Rating/3650 | |
{ 0x1c83, Gpus.NvidiaGtx10503Gb }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c8d, Gpus.NvidiaGtx1050M }, // #86, http://gpu.userbenchmark.com/SpeedTest/211022/NVIDIA-GeForce-GTX-1050 | |
{ 0x1c22, Gpus.NvidiaGtx1050M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c62, Gpus.NvidiaGtx1050M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c82, Gpus.NvidiaGtx1050Ti }, // #66, http://gpu.userbenchmark.com/Nvidia-GTX-1050-Ti/Rating/3649 | |
{ 0x1c8f, Gpus.NvidiaGtx1050Ti }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c8c, Gpus.NvidiaGtx1050TiM }, // #72, http://gpu.userbenchmark.com/SpeedTest/223242/NVIDIA-GeForce-GTX-1050-Ti | |
{ 0x1c21, Gpus.NvidiaGtx1050TiM }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c61, Gpus.NvidiaGtx1050TiM }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c03, Gpus.NvidiaGtx1060 }, // #27, http://gpu.userbenchmark.com/Nvidia-GTX-1060-6GB/Rating/3639 | |
{ 0x1c06, Gpus.NvidiaGtx1060 }, // ^^ | |
{ 0x1b83, Gpus.NvidiaGtx1060 }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c02, Gpus.NvidiaGtx10603Gb }, // #35, http://gpu.userbenchmark.com/Nvidia-GTX-1060-3GB/Rating/3646 | |
{ 0x1b84, Gpus.NvidiaGtx10603Gb }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c04, Gpus.NvidiaGtx10605Gb }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1c20, Gpus.NvidiaGtx1060M }, // #45, http://gpu.userbenchmark.com/SpeedTest/164336/NVIDIA-GeForce-GTX-1060 | |
{ 0x1c60, Gpus.NvidiaGtx1060M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1b81, Gpus.NvidiaGtx1070 }, // #15, http://gpu.userbenchmark.com/Nvidia-GTX-1070/Rating/3609 | |
{ 0x1bad, Gpus.NvidiaGtx1070 }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1ba1, Gpus.NvidiaGtx1070M }, // #21, http://gpu.userbenchmark.com/SpeedTest/164129/NVIDIA-GeForce-GTX-1070 | |
{ 0x1be1, Gpus.NvidiaGtx1070M }, // ^^ | |
{ 0x1b82, Gpus.NvidiaGtx1070Ti }, // #11, http://gpu.userbenchmark.com/Nvidia-GTX-1070-Ti/Rating/3943 | |
{ 0x1b80, Gpus.NvidiaGtx1080 }, // #8, http://gpu.userbenchmark.com/Nvidia-GTX-1080/Rating/3603 | |
{ 0x1be0, Gpus.NvidiaGtx1080M }, // #14, http://gpu.userbenchmark.com/SpeedTest/165564/NVIDIA-GeForce-GTX-1080 | |
{ 0x1ba0, Gpus.NvidiaGtx1080M }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1b06, Gpus.NvidiaGtx1080Ti }, // #3, http://gpu.userbenchmark.com/Nvidia-GTX-1080-Ti/Rating/3918 | |
{ 0x1b01, Gpus.NvidiaGtx1080Ti }, // https://pci-ids.ucw.cz/read/PC/10de | |
{ 0x1b00, Gpus.NvidiaTitanX }, // #5, http://gpu.userbenchmark.com/SpeedTest/158352/NVIDIA-TITAN-X-Pascal | |
{ 0x1b02, Gpus.NvidiaTitanXp }, // #2, http://gpu.userbenchmark.com/SpeedTest/265423/NVIDIA-TITAN-Xp | |
{ 0x1d81, Gpus.NvidiaTitanV }, // #1, http://gpu.userbenchmark.com/SpeedTest/395529/NVIDIA-TITAN-V | |
// Turing. | |
{ 0x1e87, Gpus.NvidiaGtx1180 } // ?, https://pci-ids.ucw.cz/read/PC/10de | |
}; | |
/// <remarks>List of AMD PCI IDs: https://pci-ids.ucw.cz/read/PC/1002 </remarks> | |
private static readonly Dictionary<int, Gpus> AMD_GPU_IDS = new Dictionary<int, Gpus> { | |
{ 0xffff, Gpus.AmdUnknown }, | |
// N.B. frustratingly AMD GPUs share PCI IDs, so we need to group them before teasing them apart. | |
{ 0x67b1, Gpus.AmdUnknownR9290Or390 }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x67b0, Gpus.AmdUnknownR9290XOr390X }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x67df, Gpus.AmdUnknownRx470Or480Or570Or580 }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x67ff, Gpus.AmdUnknownRx550Or560 }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x7300, Gpus.AmdUnknownR9FuryOrFuryXOrNano }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x687f, Gpus.AmdUnknownRxVega56Or64Or64Lc }, // https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x67ef, Gpus.AmdRx460 }, // #95, http://gpu.userbenchmark.com/AMD-RX-460/Rating/3641 | |
{ 0x699f, Gpus.AmdRx550 }, // #121, https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x694e, Gpus.AmdRxVegaMGl }, // #73, http://gpu.userbenchmark.com/SpeedTest/453719/Radeon-RX-Vega-M-GL-Graphics | |
{ 0x694c, Gpus.AmdRxVegaMGh }, // #49, http://gpu.userbenchmark.com/SpeedTest/422266/Radeon-RX-Vega-M-GH-Graphics | |
{ 0x6867, Gpus.AmdRxVega56 }, // #13, https://pci-ids.ucw.cz/read/PC/1002 | |
{ 0x6863, Gpus.AmdRxVegaFe }, // #12, http://gpu.userbenchmark.com/AMD-Vega-Frontier-Edition/Rating/3929 | |
}; | |
private const string LOG_DETECTED_GPU_FORMAT = "GPU: {0}\nGPU Name: {1}\nVendor: {2}\nVendor Name: {3}"; | |
private const string GPU_NAME_ID_REGEX_STRING = "[^a-z0-9]+"; | |
//----------------------------------------------------------------------------------------- | |
// Public Properties: | |
//----------------------------------------------------------------------------------------- | |
public static Vendors Vendor { get; private set; } | |
public static int VendorId { get; private set; } | |
public static string VendorName { get; private set; } | |
public static Gpus Gpu { get; private set; } | |
public static int GpuId { get; private set; } | |
public static string GpuName { get; private set; } | |
public static bool IsNvidia { get { return (Vendor == Vendors.Nvidia); } } | |
public static bool IsAmd { get { return (Vendor == Vendors.Amd ); } } | |
public static bool IsMaxwell { get { return (Gpu > Gpus.NvidiaUnknown && Gpu <= Gpus.NvidiaGtxTitanZ); } } | |
public static bool IsPascal { get { return (Gpu >= Gpus.NvidiaGtx1030 && Gpu <= Gpus.NvidiaTitanV ); } } | |
public static bool IsTuring { get { return (Gpu >= Gpus.NvidiaGtx1180 && Gpu < Gpus.AmdUnknown ); } } | |
//----------------------------------------------------------------------------------------- | |
// Constructors: | |
//----------------------------------------------------------------------------------------- | |
static GpuDetection() { | |
// get the vendor from vendor ID. | |
VendorId = SystemInfo.graphicsDeviceVendorID; | |
VendorName = SystemInfo.graphicsDeviceVendor; | |
Vendors vendor; | |
if (!VENDOR_IDS.TryGetValue(VendorId, out vendor)) { | |
vendor = Vendors.Unknown; | |
} | |
Vendor = vendor; | |
// grab GPU device ID. | |
GpuId = SystemInfo.graphicsDeviceID; | |
GpuName = SystemInfo.graphicsDeviceName; | |
Gpus gpu = Gpus.Unknown; | |
// from the vendor, attempt to find the GPU from the associated device IDs, assigning unknown if we don't find it. | |
switch (Vendor) { | |
case Vendors.Nvidia: | |
// if we can't find a value for the NVIDIA GPU, use NvidiaUnknown. | |
if (!NVIDIA_GPU_IDS.TryGetValue(GpuId, out gpu)) { | |
gpu = Gpus.NvidiaUnknown; | |
} | |
break; | |
case Vendors.Amd: | |
// if we can't find a value for the AMD GPU, use AmdUnknown. | |
if (!AMD_GPU_IDS.TryGetValue(GpuId, out gpu)) { | |
gpu = Gpus.AmdUnknown; | |
} | |
// if we end up with an unknown AMD group, determine actual GPU. | |
if (gpu >= Gpus.AmdUnknownR9290Or390 && gpu <= Gpus.AmdUnknownRxVega56Or64Or64Lc) { | |
gpu = GetGpuByAmdUnknownGroup(gpu, GpuName); | |
} | |
break; | |
} | |
Gpu = gpu; | |
LogDetectedGpu(); | |
} | |
public static void LogDetectedGpu() { | |
Debug.Log(string.Format(LOG_DETECTED_GPU_FORMAT, Gpu, GpuName, Vendor, VendorName)); | |
} | |
public static Gpus GetGpuByAmdUnknownGroup(Gpus amdGpuGroup, string name) { | |
// throw invalid op if the given Gpus value is not an unknown AMD group or we don't have a name to deal with. | |
// N.B. we're fine dealing with empty strings for names, which is a conceivable situation. | |
if (amdGpuGroup < Gpus.AmdUnknownR9290Or390 || amdGpuGroup > Gpus.AmdUnknownRxVega56Or64Or64Lc || name == null) | |
throw new InvalidOperationException(); | |
// to tease apart AMD GPUs which share PCI IDs, we have to query the name, so convert it into the most easily workable form, which | |
// is lower case with all whitespace and punctuation stripped out. | |
Regex replaceRegex = new Regex(GPU_NAME_ID_REGEX_STRING); | |
string gpuNameId = replaceRegex.Replace(name.ToLower(), string.Empty); | |
// switch over the group. | |
switch (amdGpuGroup) { | |
// N.B. there is a lot of string manipulation to detect AMD GPUs, so I will inline them all here because separating all of these | |
// out into constants would quickly become unwieldly. | |
// N.B. it is possible that GPU names contain every GPU in the group, for example, "Radeon RX 470/480/570/570X/580/580X", so, to | |
// deal with this, we make sure that each name contains only the specific ID we care about and no others, and if it does contain | |
// others, we default to the less performant one so that we're overly aggressive with our optimisations, resulting in better perf. | |
case Gpus.AmdUnknownR9290Or390: { | |
// if the name contains 390 and not 290, go with the 390, otherwise the 290. | |
return (gpuNameId.Contains("390") && !gpuNameId.Contains("290")) ? Gpus.AmdR9390 : Gpus.AmdR9290; | |
} | |
case Gpus.AmdUnknownR9290XOr390X: { | |
// if the name contains 390, go with the 390X, otherwise the 290X. | |
return (gpuNameId.Contains("390") && !gpuNameId.Contains("290")) ? Gpus.AmdR9390X : Gpus.AmdR9290X; | |
} | |
case Gpus.AmdUnknownRx470Or480Or570Or580: { | |
bool doesContain580 = gpuNameId.Contains("580"); | |
bool doesContain570 = gpuNameId.Contains("570"); | |
bool doesContain480 = gpuNameId.Contains("480"); | |
bool doesContain470 = gpuNameId.Contains("470"); | |
// handling the present of groups of three, go from 470 to 480 to 570 to 580. | |
if ( doesContain470 && doesContain480 && doesContain570 && !doesContain580) return Gpus.AmdRx470; | |
if ( doesContain470 && doesContain480 && !doesContain570 && doesContain580) return Gpus.AmdRx470; | |
if ( doesContain470 && !doesContain480 && doesContain570 && doesContain580) return Gpus.AmdRx470; | |
if (!doesContain470 && doesContain480 && doesContain570 && doesContain580) return Gpus.AmdRx480; | |
// N.B. the fact we're checking for groups of three, then two, then one, means there are many opportunities to optimise below | |
// conditions and remove redundant checks. However, it is very much unclear to the human brain how the preceding statements | |
// logically preclude others, so I'll leave them in, in full, to make it clearer that all conditions are handled. | |
// ReSharper disable ConditionIsAlwaysTrueOrFalse | |
// handling the presence of groups of two, go from 470 to 480 to 570 to 580. | |
if ( doesContain470 && doesContain480 && !doesContain570 && !doesContain580) return Gpus.AmdRx470; | |
if ( doesContain470 && !doesContain480 && doesContain570 && !doesContain580) return Gpus.AmdRx470; | |
if ( doesContain470 && !doesContain480 && !doesContain570 && doesContain580) return Gpus.AmdRx470; | |
if (!doesContain470 && doesContain480 && doesContain570 && !doesContain580) return Gpus.AmdRx480; | |
if (!doesContain470 && doesContain480 && !doesContain570 && doesContain580) return Gpus.AmdRx480; | |
if (!doesContain470 && !doesContain480 && doesContain570 && doesContain580) return Gpus.AmdRx570; | |
// handling exclusive presence of one, go in order from 580 to 570 to 480 to, otherwise, 470. | |
if (doesContain580 && !doesContain570 && !doesContain480 && !doesContain470) return Gpus.AmdRx580; | |
if (doesContain570 && !doesContain580 && !doesContain480 && !doesContain470) return Gpus.AmdRx570; | |
if (doesContain480 && !doesContain580 && !doesContain570 && !doesContain470) return Gpus.AmdRx480; | |
// ReSharper restore ConditionIsAlwaysTrueOrFalse | |
return Gpus.AmdRx470; | |
} | |
case Gpus.AmdUnknownRx550Or560: { | |
// if the name contains 560, go with the RX 560, otherwise the RX 550. | |
return (gpuNameId.Contains("560") && !gpuNameId.Contains("550")) ? Gpus.AmdRx560 : Gpus.AmdRx550; | |
} | |
case Gpus.AmdUnknownR9FuryOrFuryXOrNano: { | |
// N.B. in this example, Fury X already contains the word "Fury", so we have to get a bit creative. | |
const string furyId = "fury"; | |
const string furyXId = furyId + "x"; | |
const string nanoId = "nano"; | |
bool doesContainFury = gpuNameId.Contains(furyId); | |
bool doesContainFuryX = gpuNameId.Contains(furyXId); | |
bool doesContainNano = gpuNameId.Contains(nanoId); | |
bool doesContainFuryAndFuryX = (doesContainFuryX && gpuNameId.Replace(furyXId, string.Empty).Contains(furyId)); | |
bool doesContainAll = (doesContainFuryAndFuryX && doesContainNano); | |
// if it contains all, go with the worst, which is Nano. | |
if (doesContainAll) return Gpus.AmdR9Nano; | |
// if it contains Fury X but not also (a separate) Fury and Nano, it's Fury X. | |
if ( doesContainFuryX && !doesContainFuryAndFuryX && !doesContainNano) return Gpus.AmdR9FuryX; | |
// if it contains Fury but not Fury X, or both, but not Nano, it's Fury. | |
if (((doesContainFury && !doesContainFuryX) || doesContainFuryAndFuryX) && !doesContainNano) return Gpus.AmdR9Fury; | |
// and if all else fails, default to Nano, which is the least powerful. | |
return Gpus.AmdR9Nano; | |
} | |
case Gpus.AmdUnknownRxVega56Or64Or64Lc: { | |
// N.B. in this example, "64 LC" already contains "64", so we have to get a bit creative. | |
const string rxVega64Id = "64"; | |
const string rxVega56Id = "56"; | |
bool doesContainLc = gpuNameId.Contains("lc") || gpuNameId.Contains("liquid"); | |
bool doesContain64 = gpuNameId.Contains(rxVega64Id); | |
bool doesContain56 = gpuNameId.Contains(rxVega56Id); | |
// N.B. because string.Replace replaces all instances, we need to use a custom ReplaceAll to delete only one of the "64" instances | |
// (the one used for 64 LC). | |
bool doesContain64LcAnd64 = (doesContainLc && ReplaceFirst(gpuNameId, rxVega64Id, string.Empty).Contains(rxVega64Id)); | |
bool doesContainAll = (doesContain64LcAnd64 && doesContain56); | |
// if it contains all, go with the worst, which is 56. | |
if (doesContainAll) return Gpus.AmdRxVega56; | |
// if it contains LC but not also (a separate) 64 and 56, it's 64 LC. | |
if (doesContainLc && !doesContain64LcAnd64 && !doesContain56) return Gpus.AmdRxVega64Lc; | |
// if it contains 64 but not 64 LC, or both, but not 56, it's 64. | |
if (((doesContain64 && !doesContainLc) || doesContain64LcAnd64) && !doesContain56) return Gpus.AmdRxVega64; | |
// and if all else fails, default to 56, which is the least powerful. | |
return Gpus.AmdRxVega56; | |
} | |
} | |
// no dice, so just return unknown. | |
return Gpus.AmdUnknown; | |
} | |
//----------------------------------------------------------------------------------------- | |
// Private Methods: | |
//----------------------------------------------------------------------------------------- | |
/// <summary> | |
/// Replaces the first instance of <c>oldValue</c> with <c>newValue</c>. | |
/// </summary> | |
public static string ReplaceFirst(string @string, string oldValue, string newValue) { | |
int position = @string.IndexOf(oldValue, StringComparison.Ordinal); | |
if (position < 0) { | |
return @string; | |
} | |
return @string.Substring(0, position) + newValue + @string.Substring(position + oldValue.Length); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using NUnit.Framework; | |
public static class GpuDetectionTests { | |
//----------------------------------------------------------------------------------------- | |
// Tests: | |
//----------------------------------------------------------------------------------------- | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithTooLowGpusValue_InvalidOps() { | |
Assert.Throws<InvalidOperationException>(() => GpuDetection.GetGpuByAmdUnknownGroup(EnumPrevOrLast(GpuDetection.Gpus.AmdUnknownR9290Or390), string.Empty)); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithFirstGpusValue_DoesNotInvalidOp() { | |
Assert.DoesNotThrow(() => GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "AmdUnknownR9290Or390")); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithTooHighGpusValue_InvalidOps() { | |
Assert.Throws<InvalidOperationException>(() => GpuDetection.GetGpuByAmdUnknownGroup(EnumNextOrFirst(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc), string.Empty)); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithLastGpusValue_DoesNotInvalidOp() { | |
Assert.DoesNotThrow(() => GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "AmdUnknownR9290Or390")); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithNullName_InvalidOps() { | |
Assert.Throws<InvalidOperationException>(() => GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, null)); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithEmptyName_DoesNotInvalidOp() { | |
Assert.DoesNotThrow(() => GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, string.Empty)); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAnd290String_Returns290() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "290") == GpuDetection.Gpus.AmdR9290); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAnd390String_Returns390() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "390") == GpuDetection.Gpus.AmdR9390); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAnd290And390String_Returns290() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "290 and 390") == GpuDetection.Gpus.AmdR9290); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAndEmptyString_Returns290() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, string.Empty) == GpuDetection.Gpus.AmdR9290); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAndPciIdName_Returns290() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "Hawaii PRO [Radeon R9 290/390]") == GpuDetection.Gpus.AmdR9290); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAndWhitespaceAndPunctuationString_Returns290() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, " $:@> >) $^% !_-=+") == GpuDetection.Gpus.AmdR9290); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAndWhitespacePunctuationAnd390String_Returns390() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, "<:! %£( ) 390 @>(_+") == GpuDetection.Gpus.AmdR9390); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290Or390GroupAndWhitespaceBetweenAnd390String_Returns390() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290Or390, " 3 9 0 ") == GpuDetection.Gpus.AmdR9390); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290XOr390XGroupAnd290XString_Returns290X() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290XOr390X, "290 X") == GpuDetection.Gpus.AmdR9290X); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290XOr390XGroupAnd390XString_Returns390X() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290XOr390X, "390 X") == GpuDetection.Gpus.AmdR9390X); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290XOr390XGroupAnd290XAnd390XString_Returns290X() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290XOr390X, "290X/390X") == GpuDetection.Gpus.AmdR9290X); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290XOr390XGroupAndEmptyString_Returns290X() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290XOr390X, string.Empty) == GpuDetection.Gpus.AmdR9290X); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9290XOr390XGroupAndPciIdName_Returns290X() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9290XOr390X, "Hawaii XT / Grenada XT [Radeon R9 290X/390X]") == GpuDetection.Gpus.AmdR9290X); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd480String_Returns480() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "480") == GpuDetection.Gpus.AmdRx480); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd570String_Returns570() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "570") == GpuDetection.Gpus.AmdRx570); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd580String_Returns580() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "580") == GpuDetection.Gpus.AmdRx580); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470And480String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470/480") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd570And580String_Returns570() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "570 / 580") == GpuDetection.Gpus.AmdRx570); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470And570String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470 & 570") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd480And580String_Returns480() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "480 + 580") == GpuDetection.Gpus.AmdRx480); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470480And570String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470, 480, 570") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470480And580String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470 + 480 + 580") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470570And580String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470/570/580") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd480570And580String_Returns480() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "480 570 580") == GpuDetection.Gpus.AmdRx480); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAnd470480570And580String_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "470/480 and 570/580") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAndEmptyString_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, string.Empty) == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx470Or480Or570Or580GroupAndPciIdName_Returns470() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx470Or480Or570Or580, "Ellesmere [Radeon RX 470/480/570/570X/580/580X]") == GpuDetection.Gpus.AmdRx470); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx550Or560GroupAnd550String_Returns550() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx550Or560, " 550 ") == GpuDetection.Gpus.AmdRx550); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx550Or560GroupAnd560String_Returns560() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx550Or560, "560") == GpuDetection.Gpus.AmdRx560); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx550Or560GroupAnd550And560String_Returns550() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx550Or560, "550 AND 560") == GpuDetection.Gpus.AmdRx550); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx550Or560GroupAndEmptyString_Returns550() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx550Or560, string.Empty) == GpuDetection.Gpus.AmdRx550); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithRx550Or560GroupAndPciIdName_Returns550() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRx550Or560, "Baffin [Radeon RX 550 640SP / RX 560/560X]") == GpuDetection.Gpus.AmdRx550); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndNanoString_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Nano") == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndFuryString_ReturnsFury() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Fury") == GpuDetection.Gpus.AmdR9Fury); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndFuryXString_ReturnsFuryX() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Fury (X)") == GpuDetection.Gpus.AmdR9FuryX); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndNanoAndFuryString_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Nano / Fury") == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndFuryXAndNanoString_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "FURY X & Nano") == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndFuryAndFuryXString_ReturnsFury() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Fury + Fury (X)!") == GpuDetection.Gpus.AmdR9Fury); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndNanoAndFuryAndFuryXString_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Nano || FURY || FURY X") == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndEmptyString_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, string.Empty) == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithR9FuryOrFuryXOrNanoGroupAndPciIdName_ReturnsNano() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownR9FuryOrFuryXOrNano, "Fiji [Radeon R9 FURY / NANO Series]") == GpuDetection.Gpus.AmdR9Nano); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd56String_Returns56() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "56") == GpuDetection.Gpus.AmdRxVega56); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd64String_Returns64() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "64") == GpuDetection.Gpus.AmdRxVega64); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd64LcString_Returns64Lc() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "64 LC") == GpuDetection.Gpus.AmdRxVega64Lc); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd64LiquidCooledString_Returns64Lc() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "64 (Liquid Cooled)") == GpuDetection.Gpus.AmdRxVega64Lc); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd56And64String_Returns56() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "56 / 64") == GpuDetection.Gpus.AmdRxVega56); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd64LcAnd56String_Returns56() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "56 & 64 (liquid-cooled)") == GpuDetection.Gpus.AmdRxVega56); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd64And64LcString_Returns64() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "64 + 64 (LC)!") == GpuDetection.Gpus.AmdRxVega64); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAnd56And64And64LcString_Returns56() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "56 \\ 64 \\ 64/lc") == GpuDetection.Gpus.AmdRxVega56); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAndEmptyString_Returns56() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, string.Empty) == GpuDetection.Gpus.AmdRxVega56); | |
} | |
[Test] | |
public static void GetGpuByAmdUnknownGroup_WithVega56Or64Or64LcGroupAndPciIdName_Returns64() { | |
Assert.IsTrue(GpuDetection.GetGpuByAmdUnknownGroup(GpuDetection.Gpus.AmdUnknownRxVega56Or64Or64Lc, "Vega 10 XT [Radeon RX Vega 64]") == GpuDetection.Gpus.AmdRxVega64); | |
} | |
//----------------------------------------------------------------------------------------- | |
// Private Methods: | |
//----------------------------------------------------------------------------------------- | |
/// <summary> | |
/// Returns the next or first (if the current is the last) enumeration value. | |
/// </summary> | |
/// <typeparam name="TEnum">The generic enumeration type.</typeparam> | |
/// <remarks>The generic type name is <c>TEnum</c> to emphasise that it should be (but could conceivably not be) an enum.</remarks> | |
/// <remarks>The generic type constaints <c>IConvertible</c>, <c>IComparable</c>, <c>IFormattable</c> are all the interfaces which Enum implements, making it | |
/// less likely that this method is available to extend other types.</remarks> | |
private static TEnum EnumNextOrFirst<TEnum>(TEnum @enum) where TEnum : struct, IConvertible, IComparable, IFormattable { | |
CheckIsEnum<TEnum>(); | |
// convert the possible enum values into an array of values and chose the next or first. | |
TEnum[] array = (TEnum[])Enum.GetValues(@enum.GetType()); | |
int i = Array.IndexOf(array, @enum) + 1; | |
return (i == array.Length) ? array[0] : array[i]; | |
} | |
/// <summary> | |
/// Returns the previous or last (if the current is the first) enumeration value. | |
/// </summary> | |
/// <typeparam name="TEnum">The generic enumeration type.</typeparam> | |
/// <remarks>The generic type name is <c>TEnum</c> to emphasise that it should be (but could conceivably not be) an enum.</remarks> | |
/// <remarks>The generic type constaints <c>IConvertible</c>, <c>IComparable</c>, <c>IFormattable</c> are all the interfaces which Enum implements, making it | |
/// less likely that this method is available to extend other types.</remarks> | |
private static TEnum EnumPrevOrLast<TEnum>(TEnum @enum) where TEnum : struct, IConvertible, IComparable, IFormattable { | |
CheckIsEnum<TEnum>(); | |
// convert the possible enum values into an array of values and chose the previous or last. | |
TEnum[] array = (TEnum[])Enum.GetValues(@enum.GetType()); | |
int i = Array.IndexOf(array, @enum) - 1; | |
return (i == -1) ? array[array.Length - 1] : array[i]; | |
} | |
/// <summary> | |
/// Because we can't constrain on where TEnum : Enum, we have to check for accidental misuse. | |
/// </summary> | |
/// <typeparam name="TEnum">The type to check whether it is an enum.</typeparam> | |
private static void CheckIsEnum<TEnum>() { | |
if (!typeof(TEnum).IsEnum) { | |
throw new NotSupportedException(string.Format("Argument {0} is not an Enum.", typeof(TEnum).FullName)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
[InitializeOnLoad] | |
#endif | |
public static class QualityDesignation { | |
//----------------------------------------------------------------------------------------- | |
// Constants: | |
//----------------------------------------------------------------------------------------- | |
private static readonly Dictionary<GpuDetection.Gpus, Designations> DESIGNATIONS = new Dictionary<GpuDetection.Gpus, Designations> { | |
{ GpuDetection.Gpus.Unknown, Designations.Default }, | |
{ GpuDetection.Gpus.NvidiaUnknown, Designations.Default }, | |
// Maxwell. | |
{ GpuDetection.Gpus.NvidiaGtx780, Designations.VeryLow }, // #42, http://gpu.userbenchmark.com/Nvidia-GTX-780/Rating/2164 | |
{ GpuDetection.Gpus.NvidiaGtx780M, Designations.VeryLow }, // #83, http://gpu.userbenchmark.com/SpeedTest/7760/NVIDIA-GeForce-GTX-780M | |
{ GpuDetection.Gpus.NvidiaGtx780Ti, Designations.VeryLow }, // #28, http://gpu.userbenchmark.com/Nvidia-GTX-780-Ti/Rating/2165 | |
{ GpuDetection.Gpus.NvidiaGtx960, Designations.VeryLow }, // #63, http://gpu.userbenchmark.com/Nvidia-GTX-960/Rating/3165 | |
{ GpuDetection.Gpus.NvidiaGtx960M, Designations.VeryLow }, // #128, http://gpu.userbenchmark.com/SpeedTest/27242/NVIDIA-GeForce-GTX-960M | |
{ GpuDetection.Gpus.NvidiaGtx965M, Designations.VeryLow }, // #93, http://gpu.userbenchmark.com/SpeedTest/24481/NVIDIA-GeForce-GTX-965M | |
{ GpuDetection.Gpus.NvidiaGtx970, Designations.VeryLow }, // #38, http://gpu.userbenchmark.com/Nvidia-GTX-970/Rating/2577 | |
{ GpuDetection.Gpus.NvidiaGtx970M, Designations.VeryLow }, // #67, http://gpu.userbenchmark.com/SpeedTest/17319/NVIDIA-GeForce-GTX-970M | |
{ GpuDetection.Gpus.NvidiaGtx980, Designations.Low }, // #26, http://gpu.userbenchmark.com/Nvidia-GTX-980/Rating/2576 | |
{ GpuDetection.Gpus.NvidiaGtx980M, Designations.VeryLow }, // #50, http://gpu.userbenchmark.com/SpeedTest/15596/NVIDIA-GeForce-GTX-980M | |
{ GpuDetection.Gpus.NvidiaGtx980Ti, Designations.Default }, // #16, http://gpu.userbenchmark.com/Nvidia-GTX-980-Ti/Rating/3439 | |
{ GpuDetection.Gpus.NvidiaGtxTitan, Designations.VeryLow }, // #41, http://gpu.userbenchmark.com/Nvidia-GTX-Titan/Rating/2191 | |
{ GpuDetection.Gpus.NvidiaGtxTitanLe, Designations.VeryLow }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ GpuDetection.Gpus.NvidiaGtxTitanBlack, Designations.Low }, // #31, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-Black/Rating/3158 | |
{ GpuDetection.Gpus.NvidiaGtxTitanX, Designations.Default }, // #17, http://gpu.userbenchmark.com/Nvidia-GTX-Titan-X/Rating/3282 | |
{ GpuDetection.Gpus.NvidiaGtxTitanZ, Designations.Low }, // #33, http://gpu.userbenchmark.com/SpeedTest/17751/NVIDIA-GeForce-GTX-TITAN-Z | |
// Pascal. | |
{ GpuDetection.Gpus.NvidiaGtx1030, Designations.VeryLow }, // #136, http://gpu.userbenchmark.com/SpeedTest/283726/NVIDIA-GeForce-GT-1030 | |
{ GpuDetection.Gpus.NvidiaGtx1050, Designations.VeryLow }, // #78, http://gpu.userbenchmark.com/Nvidia-GTX-1050/Rating/3650 | |
{ GpuDetection.Gpus.NvidiaGtx10503Gb, Designations.VeryLow }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ GpuDetection.Gpus.NvidiaGtx1050M, Designations.VeryLow }, // #86, http://gpu.userbenchmark.com/SpeedTest/211022/NVIDIA-GeForce-GTX-1050 | |
{ GpuDetection.Gpus.NvidiaGtx1050Ti, Designations.VeryLow }, // #66, http://gpu.userbenchmark.com/Nvidia-GTX-1050-Ti/Rating/3649 | |
{ GpuDetection.Gpus.NvidiaGtx1050TiM, Designations.VeryLow }, // #72, http://gpu.userbenchmark.com/SpeedTest/223242/NVIDIA-GeForce-GTX-1050-Ti | |
{ GpuDetection.Gpus.NvidiaGtx1060, Designations.Low }, // #27, http://gpu.userbenchmark.com/Nvidia-GTX-1060-6GB/Rating/3639 | |
{ GpuDetection.Gpus.NvidiaGtx10603Gb, Designations.Low }, // #35, http://gpu.userbenchmark.com/Nvidia-GTX-1060-3GB/Rating/3646 | |
{ GpuDetection.Gpus.NvidiaGtx10605Gb, Designations.Low }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ GpuDetection.Gpus.NvidiaGtx1060M, Designations.VeryLow }, // #45, http://gpu.userbenchmark.com/SpeedTest/164336/NVIDIA-GeForce-GTX-1060 | |
{ GpuDetection.Gpus.NvidiaGtx1070, Designations.Default }, // #15, http://gpu.userbenchmark.com/Nvidia-GTX-1070/Rating/3609 | |
{ GpuDetection.Gpus.NvidiaGtx1070M, Designations.Default }, // #21, http://gpu.userbenchmark.com/SpeedTest/164129/NVIDIA-GeForce-GTX-1070 | |
{ GpuDetection.Gpus.NvidiaGtx1070Ti, Designations.High }, // #11, http://gpu.userbenchmark.com/Nvidia-GTX-1070-Ti/Rating/3943 | |
{ GpuDetection.Gpus.NvidiaGtx1080, Designations.High }, // #8, http://gpu.userbenchmark.com/Nvidia-GTX-1080/Rating/3603 | |
{ GpuDetection.Gpus.NvidiaGtx1080M, Designations.Default }, // #14, http://gpu.userbenchmark.com/SpeedTest/165564/NVIDIA-GeForce-GTX-1080 | |
{ GpuDetection.Gpus.NvidiaGtx1080Ti, Designations.High }, // #3, http://gpu.userbenchmark.com/Nvidia-GTX-1080-Ti/Rating/3918 | |
{ GpuDetection.Gpus.NvidiaTitanX, Designations.High }, // #5, http://gpu.userbenchmark.com/SpeedTest/158352/NVIDIA-TITAN-X-Pascal | |
{ GpuDetection.Gpus.NvidiaTitanXp, Designations.High }, // #2, http://gpu.userbenchmark.com/SpeedTest/265423/NVIDIA-TITAN-Xp | |
{ GpuDetection.Gpus.NvidiaTitanV, Designations.High }, // #1, http://gpu.userbenchmark.com/SpeedTest/395529/NVIDIA-TITAN-V | |
// Turing. | |
{ GpuDetection.Gpus.NvidiaGtx1180, Designations.High }, // ?, https://pci-ids.ucw.cz/read/PC/10de | |
{ GpuDetection.Gpus.AmdUnknown, Designations.Default }, | |
{ GpuDetection.Gpus.AmdR9290, Designations.VeryLow }, // #40, http://gpu.userbenchmark.com/AMD-R9-290/Rating/2171 | |
{ GpuDetection.Gpus.AmdR9290X, Designations.VeryLow }, // #32, http://gpu.userbenchmark.com/AMD-R9-290X/Rating/2166 | |
{ GpuDetection.Gpus.AmdR9390, Designations.VeryLow }, // #37, http://gpu.userbenchmark.com/AMD-R9-390/Rating/3481 | |
{ GpuDetection.Gpus.AmdR9390X, Designations.Low }, // #29, http://gpu.userbenchmark.com/AMD-R9-390X/Rating/3497 | |
{ GpuDetection.Gpus.AmdRx460, Designations.VeryLow }, // #95, http://gpu.userbenchmark.com/AMD-RX-460/Rating/3641 | |
{ GpuDetection.Gpus.AmdRx470, Designations.VeryLow }, // #47, http://gpu.userbenchmark.com/AMD-RX-470/Rating/3640 | |
{ GpuDetection.Gpus.AmdRx480, Designations.VeryLow }, // #39, http://gpu.userbenchmark.com/AMD-RX-480/Rating/3634 | |
{ GpuDetection.Gpus.AmdRx550, Designations.VeryLow }, // #121, http://gpu.userbenchmark.com/AMD-RX-550/Rating/3925 | |
{ GpuDetection.Gpus.AmdRx560, Designations.VeryLow }, // #82, http://gpu.userbenchmark.com/AMD-RX-560/Rating/ | |
{ GpuDetection.Gpus.AmdRx570, Designations.VeryLow }, // #44, http://gpu.userbenchmark.com/AMD-RX-570/Rating/3924 | |
{ GpuDetection.Gpus.AmdRx580, Designations.Low }, // #30, http://gpu.userbenchmark.com/AMD-RX-580/Rating/3923 | |
{ GpuDetection.Gpus.AmdR9Nano, Designations.Low }, // #28, http://gpu.userbenchmark.com/SpeedTest/58413/AMD-Radeon-TM-R9-Fury | |
{ GpuDetection.Gpus.AmdR9Fury, Designations.Low }, // #24, http://gpu.userbenchmark.com/AMD-R9-Fury/Rating/3509 | |
{ GpuDetection.Gpus.AmdR9FuryX, Designations.Default }, // #23, http://gpu.userbenchmark.com/AMD-R9-Fury-X/Rating/3498 | |
{ GpuDetection.Gpus.AmdRxVegaMGl, Designations.VeryLow }, // #73, http://gpu.userbenchmark.com/SpeedTest/453719/Radeon-RX-Vega-M-GL-Graphics | |
{ GpuDetection.Gpus.AmdRxVegaMGh, Designations.VeryLow }, // #49, http://gpu.userbenchmark.com/SpeedTest/422266/Radeon-RX-Vega-M-GH-Graphics | |
{ GpuDetection.Gpus.AmdRxVega56, Designations.High }, // #13, http://gpu.userbenchmark.com/AMD-RX-Vega-56/Rating/3938 | |
{ GpuDetection.Gpus.AmdRxVegaFe, Designations.High }, // #12, http://gpu.userbenchmark.com/AMD-Vega-Frontier-Edition/Rating/3929 | |
{ GpuDetection.Gpus.AmdRxVega64, Designations.High }, // #10, http://gpu.userbenchmark.com/AMD-RX-Vega-64/Rating/3933 | |
{ GpuDetection.Gpus.AmdRxVega64Lc, Designations.High }, // #7, http://gpu.userbenchmark.com/SpeedTest/353890/Radeon-RX-Vega | |
}; | |
private const string LOG_DESIGNATION_FORMAT = "Quality Designation: {0}"; | |
//----------------------------------------------------------------------------------------- | |
// Type Definitions: | |
//----------------------------------------------------------------------------------------- | |
public enum Designations { | |
Undetermined = -1, | |
Default, | |
VeryLow, | |
Low, | |
High | |
} | |
//----------------------------------------------------------------------------------------- | |
// Private Fields: | |
//----------------------------------------------------------------------------------------- | |
private static Designations _designation = Designations.Undetermined; | |
//----------------------------------------------------------------------------------------- | |
// Public Properties: | |
//----------------------------------------------------------------------------------------- | |
public static Designations Designation { | |
get { | |
// return the designation if it has already been determined. | |
if (_designation != Designations.Undetermined) return _designation; | |
// try to determine quality from detected GPU, ensuring we set to Default if we don't find a designation. | |
if (!DESIGNATIONS.TryGetValue(GpuDetection.Gpu, out _designation)) { | |
_designation = Designations.Default; | |
} | |
return _designation; | |
} | |
} | |
//----------------------------------------------------------------------------------------- | |
// Constructors: | |
//----------------------------------------------------------------------------------------- | |
static QualityDesignation() { | |
LogDesignation(); | |
} | |
//----------------------------------------------------------------------------------------- | |
// Public Methods: | |
//----------------------------------------------------------------------------------------- | |
public static void LogDesignation() { | |
Debug.Log(string.Format(LOG_DESIGNATION_FORMAT, Designation)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment