启动时在日志中记录当前平台的所有 GPU (#3893)

This commit is contained in:
Glavo
2025-05-09 10:08:08 +08:00
committed by GitHub
parent 06a89dd6a9
commit 1da98d6d67
15 changed files with 1883 additions and 31 deletions

View File

@@ -40,6 +40,7 @@ import org.jackhuang.hmcl.util.platform.Architecture;
import org.jackhuang.hmcl.util.platform.CommandBuilder;
import org.jackhuang.hmcl.util.platform.NativeUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.SystemInfo;
import java.io.File;
import java.io.IOException;
@@ -258,6 +259,9 @@ public final class Launcher extends Application {
LOG.info("XDG Session Type: " + System.getenv("XDG_SESSION_TYPE"));
LOG.info("XDG Current Desktop: " + System.getenv("XDG_CURRENT_DESKTOP"));
}
Lang.thread(SystemInfo::initialize, "Detection System Information", true);
launch(Launcher.class, args);
} catch (Throwable e) { // Fucking JavaFX will suppress the exception and will break our crash reporter.
CRASH_REPORTER.uncaughtException(Thread.currentThread(), e);

View File

@@ -46,7 +46,6 @@ import org.jackhuang.hmcl.util.TaskCancellationAction;
import org.jackhuang.hmcl.util.io.CSVTable;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
@@ -157,7 +156,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
Path path = Paths.get("hmcl-mod-update-list-" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")) + ".csv").toAbsolutePath();
Controllers.taskDialog(Task.runAsync(() -> {
CSVTable csvTable = CSVTable.createEmpty();
CSVTable csvTable = new CSVTable();
csvTable.set(0, 0, "Source File Name");
csvTable.set(1, 0, "Current Version");
@@ -171,7 +170,7 @@ public class ModUpdatesPage extends BorderPane implements DecoratorPage {
csvTable.set(3, i + 1, objects.get(i).source.get());
}
csvTable.write(Files.newOutputStream(path));
csvTable.write(path);
FXUtils.showFileInExplorer(path);
}).whenComplete(Schedulers.javafx(), exception -> {

View File

@@ -16,6 +16,7 @@ dependencies {
api(libs.jsoup)
api(libs.chardet)
api(libs.jna)
api(libs.pci.ids)
compileOnlyApi(libs.jetbrains.annotations)
}

View File

@@ -19,66 +19,113 @@
package org.jackhuang.hmcl.util.io;
import org.jackhuang.hmcl.util.InfiniteSizeList;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public final class CSVTable {
private final List<List<String>> table = new InfiniteSizeList<>();
private int columnCount = 0;
private int rowCount = 0;
private final InfiniteSizeList<InfiniteSizeList<String>> table = new InfiniteSizeList<>();
private CSVTable() {
public CSVTable() {
}
public static CSVTable createEmpty() {
return new CSVTable();
public int getColumnCount() {
return columnCount;
}
public String get(int x, int y) {
public int getRowCount() {
return rowCount;
}
public @NotNull String get(int x, int y) {
List<String> row = table.get(y);
if (row == null) {
return null;
return "";
}
return row.get(x);
String value = row.get(x);
return value != null ? value : "";
}
public void set(int x, int y, String txt) {
List<String> row = table.get(y);
if (x < 0 || y < 0)
throw new IllegalArgumentException("x or y must be greater than or equal to 0");
InfiniteSizeList<String> row = table.get(y);
if (row == null) {
row = new InfiniteSizeList<>(x);
table.set(y, row);
}
row.set(x, txt);
columnCount = Integer.max(columnCount, x + 1);
rowCount = Integer.max(rowCount, y + 1);
}
public void write(OutputStream outputStream) throws IOException {
try (PrintWriter printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
outputStream, StandardCharsets.UTF_8)), false
)) {
for (List<String> row : this.table) {
if (row != null) {
for (int j = 0; j < row.size(); j++) {
String txt = row.get(j);
if (txt != null) {
printWriter.write(this.escape(txt));
}
public void write(Path file) throws IOException {
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
write(writer);
}
}
if (j != row.size() - 1) {
printWriter.write(',');
public void write(Appendable out) throws IOException {
for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
List<String> row = this.table.get(rowIndex);
if (row != null) {
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
String txt = row.get(columnIndex);
if (txt != null) {
if (txt.indexOf('"') < 0 && txt.indexOf(',') < 0 && txt.indexOf('\n') < 0 && txt.indexOf('\r') < 0)
out.append(txt);
else {
out.append('"');
for (int i = 0; i < txt.length(); i++) {
char c = txt.charAt(i);
switch (c) {
case '"':
out.append("\\\"");
break;
case '\r':
out.append("\\r");
break;
case '\n':
out.append("\\n");
break;
default:
out.append(c);
break;
}
}
out.append('"');
}
}
}
printWriter.write('\n');
if (columnIndex < columnCount - 1)
out.append(',');
}
} else {
for (int columnIndex = 0; columnIndex < columnCount - 1; columnIndex++) {
out.append(',');
}
}
out.append('\n');
}
}
private String escape(String txt) {
if (!txt.contains("\"") && !txt.contains(",")) {
return txt;
} else {
return "\"" + txt.replace("\"", "\"\"") + "\"";
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
try {
write(builder);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return builder.toString();
}
}

View File

@@ -0,0 +1,85 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform;
import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard;
import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector;
import org.jackhuang.hmcl.util.platform.linux.LinuxHardwareDetector;
import org.jackhuang.hmcl.util.platform.macos.MacOSHardwareDetector;
import org.jackhuang.hmcl.util.platform.windows.WindowsHardwareDetector;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
public final class SystemInfo {
private static final class Holder {
public static final HardwareDetector DETECTOR;
static {
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS)
DETECTOR = new WindowsHardwareDetector();
else if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX)
DETECTOR = new LinuxHardwareDetector();
else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX)
DETECTOR = new MacOSHardwareDetector();
else
DETECTOR = new HardwareDetector();
}
public static final @Nullable List<GraphicsCard> GRAPHICS_CARDS = DETECTOR.detectGraphicsCards();
}
public static void initialize() {
StringBuilder builder = new StringBuilder("System Info:");
List<GraphicsCard> graphicsCards = getGraphicsCards();
if (graphicsCards != null) {
if (graphicsCards.isEmpty())
builder.append("\n - GPU: Not Found");
else if (graphicsCards.size() == 1)
builder.append("\n - GPU: ").append(graphicsCards.get(0));
else {
int index = 1;
for (GraphicsCard graphicsCard : graphicsCards) {
builder.append("\n - GPU ").append(index++).append(": ").append(graphicsCard);
}
}
}
OperatingSystem.PhysicalMemoryStatus memoryStatus = OperatingSystem.getPhysicalMemoryStatus();
if (memoryStatus.getTotal() > 0 && memoryStatus.getAvailable() > 0) {
builder.append("\n - Memory: ")
.append(String.format("%.2f GiB / %.2f GiB (%d%%)",
memoryStatus.getUsedGB(), memoryStatus.getTotalGB(),
(int) (((double) memoryStatus.getUsed() / memoryStatus.getTotal()) * 100)
));
}
LOG.info(builder.toString());
}
public static @Nullable List<GraphicsCard> getGraphicsCards() {
return Holder.GRAPHICS_CARDS;
}
private SystemInfo() {
}
}

View File

@@ -0,0 +1,261 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.hardware;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author Glavo
*/
public final class GraphicsCard {
public static Builder builder() {
return new Builder();
}
private final String name;
private final @Nullable Vendor vendor;
private final @Nullable Type type;
private final @Nullable String driver;
private final @Nullable String driverVersion;
private GraphicsCard(String name, @Nullable Vendor vendor, @Nullable Type type, @Nullable String driver, @Nullable String driverVersion) {
this.name = Objects.requireNonNull(name);
this.vendor = vendor;
this.type = type;
this.driver = driver;
this.driverVersion = driverVersion;
}
public String getName() {
return name;
}
public @Nullable Vendor getVendor() {
return vendor;
}
public @Nullable String getDriverVersion() {
return driverVersion;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(name);
if (type != null) {
builder.append(" [").append(type).append(']');
}
return builder.toString();
}
public static final class Vendor {
public static final Vendor INTEL = new Vendor("Intel");
public static final Vendor NVIDIA = new Vendor("NVIDIA");
public static final Vendor AMD = new Vendor("AMD");
public static final Vendor APPLE = new Vendor("Apple");
public static final Vendor QUALCOMM = new Vendor("Qualcomm");
public static final Vendor MTK = new Vendor("MTK");
public static final Vendor VMWARE = new Vendor("VMware");
public static final Vendor PARALLEL = new Vendor("Parallel");
public static final Vendor MICROSOFT = new Vendor("Microsoft");
public static final Vendor MOORE_THREADS = new Vendor("Moore Threads");
public static final Vendor BROADCOM = new Vendor("Broadcom");
public static final Vendor IMG = new Vendor("Imagination");
public static final Vendor LOONGSON = new Vendor("Loongson");
public static final Vendor JINGJIA_MICRO = new Vendor("Jingjia Micro");
public static final Vendor HUAWEI = new Vendor("Huawei");
public static final Vendor ZHAOXIN = new Vendor("Zhaoxin");
public static @Nullable Vendor getKnown(String name) {
if (name == null)
return null;
String lower = name.toLowerCase(Locale.ROOT);
if (lower.startsWith("intel")) return INTEL;
if (lower.startsWith("nvidia")) return NVIDIA;
if (lower.startsWith("advanced micro devices")
|| (lower.startsWith("amd") && !(lower.length() > 3 && Character.isAlphabetic(lower.charAt(3)))))
return AMD;
if (lower.equals("brcm") || lower.startsWith("broadcom")) return BROADCOM;
if (lower.startsWith("mediatek")) return MTK;
if (lower.startsWith("qualcomm")) return QUALCOMM;
if (lower.startsWith("apple")) return APPLE;
if (lower.startsWith("microsoft")) return MICROSOFT;
if (lower.startsWith("imagination") || lower.equals("img")) return IMG;
if (lower.startsWith("loongson")) return LOONGSON;
if (lower.startsWith("moore threads")) return MOORE_THREADS;
if (lower.startsWith("jingjia")) return JINGJIA_MICRO;
if (lower.startsWith("huawei")) return HUAWEI;
if (lower.startsWith("zhaoxin")) return ZHAOXIN;
return null;
}
@Contract("null -> null; !null -> !null")
public static Vendor of(String name) {
if (name == null)
return null;
Vendor known = getKnown(name);
return known != null ? known : new Vendor(name);
}
public static @Nullable Vendor ofId(int vendorId) {
// https://devicehunt.com/all-pci-vendors
switch (vendorId) {
case 0x106b:
return APPLE;
case 0x1002:
case 0x1022:
case 0x1dd8: // AMD Pensando Systems
case 0x1924: // AMD Solarflare
return AMD;
case 0x8086:
case 0x8087:
case 0x03e7:
return INTEL;
case 0x0955:
case 0x10de:
case 0x12d2:
return NVIDIA;
case 0x1ed5:
return MOORE_THREADS;
case 0x168c:
case 0x5143:
return QUALCOMM;
case 0x14c3:
return MTK;
case 0x15ad:
return VMWARE;
case 0x1ab8:
return PARALLEL;
case 0x1414:
return MICROSOFT;
case 0x182f:
case 0x14e4:
return BROADCOM;
case 0x0014:
return LOONGSON;
case 0x0731:
return JINGJIA_MICRO;
case 0x19e5:
return HUAWEI;
case 0x1d17:
return ZHAOXIN;
default:
return null;
}
}
private final String name;
public Vendor(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
return o instanceof Vendor && name.equals(((Vendor) o).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return name;
}
}
public enum Type {
Integrated,
Discrete
}
public static final class Builder {
private String name;
private Vendor vendor;
private Type type;
private String driver;
private String driverVersion;
public GraphicsCard build() {
if (name == null)
throw new IllegalStateException("Name not set");
return new GraphicsCard(name, vendor, type, driver, driverVersion);
}
public String getName() {
return name;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public Vendor getVendor() {
return vendor;
}
public Builder setVendor(Vendor vendor) {
this.vendor = vendor;
return this;
}
public Type getType() {
return type;
}
public Builder setType(Type type) {
this.type = type;
return this;
}
public String getDriver() {
return driver;
}
public Builder setDriver(String driver) {
this.driver = driver;
return this;
}
public String getDriverVersion() {
return driverVersion;
}
public Builder setDriverVersion(String driverVersion) {
this.driverVersion = driverVersion;
return this;
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.hardware;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Glavo
*/
public class HardwareDetector {
public @Nullable List<GraphicsCard> detectGraphicsCards() {
return null;
}
}

View File

@@ -0,0 +1,315 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.linux;
import org.glavo.pci.ids.PCIIDsDatabase;
import org.glavo.pci.ids.model.Device;
import org.glavo.pci.ids.model.Vendor;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard;
import java.io.*;
import java.lang.ref.SoftReference;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
/**
* @author Glavo
* @see <a href="https://github.com/fastfetch-cli/fastfetch/blob/33205326683fd89ec63204f83549839e2374c286/src/detection/gpu/gpu_linux.c">gpu_linux.c</a>
*/
final class LinuxGPUDetector {
private static volatile SoftReference<PCIIDsDatabase> databaseCache;
private static final Pattern PCI_MODALIAS_PATTERN =
Pattern.compile("pci:v(?<vendorId>\\p{XDigit}{8})d(?<deviceId>\\p{XDigit}{8})sv(?<subVendorId>\\p{XDigit}{8})sd(?<subDeviceId>\\p{XDigit}{8})bc(?<classId>\\p{XDigit}{2})sc(?<subclassId>\\p{XDigit}{2})i\\p{XDigit}{2}");
private static final Pattern PCI_DEVICE_PATTERN =
Pattern.compile("(?<pciDomain>\\p{XDigit}+):(?<pciBus>\\p{XDigit}+):(?<pciDevice>\\p{XDigit}+)\\.(?<pciFunc>\\p{XDigit}+)");
private static final Pattern OF_DEVICE_PATTERN =
Pattern.compile("of:NgpuT[^C]*C(?<compatible>.*)");
private static PCIIDsDatabase getPCIIDsDatabase() {
SoftReference<PCIIDsDatabase> databaseWeakReference = LinuxGPUDetector.databaseCache;
PCIIDsDatabase pciIDsDatabase;
if (databaseCache != null) {
pciIDsDatabase = databaseWeakReference.get();
if (pciIDsDatabase != null) {
return pciIDsDatabase;
}
}
for (String path : new String[]{
"/usr/share/misc/pci.ids",
"/usr/share/hwdata/pci.ids",
"/usr/local/share/hwdata/pci.ids"
}) {
Path p = Paths.get(path);
if (Files.isRegularFile(p)) {
try {
pciIDsDatabase = PCIIDsDatabase.load(p);
databaseCache = new SoftReference<>(pciIDsDatabase);
return pciIDsDatabase;
} catch (IOException e) {
return null;
}
}
}
return null;
}
private static void detectDriver(GraphicsCard.Builder builder, Path deviceDir) {
try {
Path driverDir = Files.readSymbolicLink(deviceDir.resolve("driver"));
if (driverDir.getNameCount() > 0) {
String name = driverDir.getName(driverDir.getNameCount() - 1).toString();
builder.setDriver(name);
Path versionFile = deviceDir.resolve("driver/module/version");
if (Files.isRegularFile(versionFile)) {
builder.setDriverVersion(FileUtils.readText(versionFile).trim());
} else if ("zx".equals(name)) {
versionFile = deviceDir.resolve("zx_info/driver_version");
if (Files.isRegularFile(versionFile)) {
builder.setDriverVersion(FileUtils.readText(versionFile).trim());
}
}
}
} catch (IOException ignored) {
}
}
private static GraphicsCard detectPCI(Path deviceDir, String modalias) throws IOException {
Matcher matcher = PCI_MODALIAS_PATTERN.matcher(modalias);
if (!matcher.matches())
return null;
GraphicsCard.Builder builder = GraphicsCard.builder();
int vendorId = Integer.parseInt(matcher.group("vendorId"), 16);
int deviceId = Integer.parseInt(matcher.group("deviceId"), 16);
int classId = Integer.parseInt(matcher.group("classId"), 16);
int subclassId = Integer.parseInt(matcher.group("subclassId"), 16);
if (classId != 0x03) // PCI_BASE_CLASS_DISPLAY
return null; // Not a GPU device
Path pciPath = Files.readSymbolicLink(deviceDir);
int nameCount = pciPath.getNameCount();
if (nameCount == 0)
return null;
matcher = PCI_DEVICE_PATTERN.matcher(pciPath.getName(nameCount - 1).toString());
if (!matcher.matches())
return null;
int pciDomain = Integer.parseInt(matcher.group("pciDomain"), 16);
int pciBus = Integer.parseInt(matcher.group("pciBus"), 16);
int pciDevice = Integer.parseInt(matcher.group("pciDevice"), 16);
int pciFunc = Integer.parseInt(matcher.group("pciFunc"), 16);
builder.setVendor(GraphicsCard.Vendor.ofId(vendorId));
detectDriver(builder, deviceDir);
try {
if (builder.getVendor() == GraphicsCard.Vendor.AMD) {
Path hwmon = deviceDir.resolve("hwmon");
try (Stream<Path> subDirs = Files.list(hwmon)) {
for (Path subDir : Lang.toIterable(subDirs)) {
if (Files.isDirectory(subDir) && !subDir.getFileName().toString().startsWith(".")) {
builder.setType(Files.exists(subDir.resolve("in1_input"))
? GraphicsCard.Type.Integrated
: GraphicsCard.Type.Discrete);
break;
}
}
} catch (IOException ignored) {
}
Path revisionFile = deviceDir.resolve("revision");
if (Files.isRegularFile(revisionFile)) {
String revisionString = FileUtils.readText(revisionFile).trim();
int revision = Integer.decode(revisionString);
String prefix = String.format("%X,\t%X,\t", deviceId, revision);
//noinspection DataFlowIssue
try (BufferedReader reader = new BufferedReader(new InputStreamReader(
LinuxHardwareDetector.class.getResourceAsStream("/assets/platform/amdgpu.ids"), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith(prefix)) {
builder.setName(line.substring(prefix.length()));
break;
}
}
}
}
} else if (builder.getVendor() == GraphicsCard.Vendor.INTEL) {
builder.setType(pciDevice == 20 ? GraphicsCard.Type.Integrated : GraphicsCard.Type.Discrete);
}
} catch (Throwable ignored) {
}
if (builder.getName() == null || builder.getVendor() == null) {
PCIIDsDatabase database = getPCIIDsDatabase();
if (database != null) {
Vendor vendor = database.findVendor(vendorId);
if (vendor != null) {
if (builder.getVendor() == null)
builder.setVendor(GraphicsCard.Vendor.of(vendor.getName()));
if (builder.getName() == null) {
Device device = vendor.getDevices().get(deviceId);
if (device != null) {
matcher = Pattern.compile(".*\\[(?<name>.*)]").matcher(device.getName());
if (matcher.matches())
builder.setName(builder.getVendor() + " " + matcher.group("name"));
else
builder.setName(builder.getVendor() + " " + device.getName());
}
}
}
}
}
if (builder.getName() == null) {
String subclassStr;
switch (subclassId) {
case 0: // PCI_CLASS_DISPLAY_VGA
subclassStr = " (VGA compatible)";
break;
case 1: // PCI_CLASS_DISPLAY_XGA
subclassStr = " (XGA compatible)";
break;
case 2: // PCI_CLASS_DISPLAY_3D
subclassStr = " (3D)";
break;
default:
subclassStr = "";
}
builder.setName(String.format("%s Device %04X%s",
builder.getVendor() != null ? builder.getVendor().toString() : "Unknown",
deviceId, subclassStr));
}
if (builder.getType() == null) {
if (builder.getVendor() == GraphicsCard.Vendor.NVIDIA) {
if (builder.getName().startsWith("GeForce")
|| builder.getName().startsWith("Quadro")
|| builder.getName().startsWith("Tesla"))
builder.setType(GraphicsCard.Type.Discrete);
} else if (builder.getVendor() == GraphicsCard.Vendor.MOORE_THREADS) {
if (builder.getName().startsWith("MTT "))
builder.setType(GraphicsCard.Type.Discrete);
}
}
return builder.build();
}
private static GraphicsCard detectOF(Path deviceDir, String modalias) throws IOException {
Matcher matcher = OF_DEVICE_PATTERN.matcher(modalias);
if (!matcher.matches())
return null;
GraphicsCard.Builder builder = new GraphicsCard.Builder();
String compatible = matcher.group("compatible");
int idx = compatible.indexOf(',');
if (idx < 0) {
builder.setName(compatible.trim());
} else {
String vendorName = compatible.substring(0, idx).trim();
GraphicsCard.Vendor vendor = GraphicsCard.Vendor.getKnown(vendorName);
if (vendor == null)
vendor = new GraphicsCard.Vendor(vendorName.toUpperCase(Locale.ROOT));
builder.setName(vendor + " " + compatible.substring(idx + 1).trim());
builder.setVendor(vendor);
}
builder.setType(GraphicsCard.Type.Integrated);
detectDriver(builder, deviceDir);
return builder.build();
}
public static List<GraphicsCard> detectAll() {
Path drm = Paths.get("/sys/class/drm");
if (!Files.isDirectory(drm))
return Collections.emptyList();
ArrayList<GraphicsCard> cards = new ArrayList<>();
try (Stream<Path> stream = Files.list(drm)) {
for (Path deviceRoot : Lang.toIterable(stream)) {
Path dirName = deviceRoot.getFileName();
if (dirName == null)
continue;
String name = dirName.toString();
if (!name.startsWith("card") || name.indexOf('-') >= 0)
continue;
Path deviceDir = deviceRoot.resolve("device");
Path modaliasFile = deviceDir.resolve("modalias");
if (!Files.isRegularFile(modaliasFile))
continue;
try {
String modalias = FileUtils.readText(modaliasFile).trim();
GraphicsCard graphicsCard = null;
if (modalias.startsWith("pci:"))
graphicsCard = detectPCI(deviceDir, modalias);
else if (modalias.startsWith("of:"))
graphicsCard = detectOF(deviceDir, modalias);
if (graphicsCard != null)
cards.add(graphicsCard);
} catch (IOException ignored) {
}
}
} catch (Throwable e) {
LOG.warning("Failed to get graphics card info", e);
} finally {
databaseCache = null;
System.gc();
}
return Collections.unmodifiableList(cards);
}
private LinuxGPUDetector() {
}
}

View File

@@ -0,0 +1,37 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.linux;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard;
import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector;
import java.util.List;
/**
* @author Glavo
*/
public final class LinuxHardwareDetector extends HardwareDetector {
@Override
public List<GraphicsCard> detectGraphicsCards() {
if (OperatingSystem.CURRENT_OS != OperatingSystem.LINUX)
return null;
return LinuxGPUDetector.detectAll();
}
}

View File

@@ -0,0 +1,126 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.macos;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard;
import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
/**
* @author Glavo
*/
public final class MacOSHardwareDetector extends HardwareDetector {
@Override
public List<GraphicsCard> detectGraphicsCards() {
if (OperatingSystem.CURRENT_OS != OperatingSystem.OSX)
return null;
Process process = null;
String json = null;
try {
File devNull = new File("/dev/null");
Process finalProcess = process = new ProcessBuilder("/usr/sbin/system_profiler",
"SPDisplaysDataType",
"-json")
.redirectInput(devNull)
.redirectError(devNull)
.start();
CompletableFuture<String> future = CompletableFuture.supplyAsync(Lang.wrap(() ->
IOUtils.readFullyAsString(finalProcess.getInputStream(), OperatingSystem.NATIVE_CHARSET)),
Schedulers.io());
if (!process.waitFor(15, TimeUnit.SECONDS))
throw new TimeoutException();
if (process.exitValue() != 0)
throw new IOException("Bad exit code: " + process.exitValue());
json = future.get();
JsonObject object = JsonUtils.GSON.fromJson(json, JsonObject.class);
JsonArray spDisplaysDataType = object.getAsJsonArray("SPDisplaysDataType");
if (spDisplaysDataType != null) {
ArrayList<GraphicsCard> cards = new ArrayList<>();
for (JsonElement element : spDisplaysDataType) {
JsonObject item = element.getAsJsonObject();
JsonElement deviceType = item.get("sppci_device_type");
if (deviceType == null || !"spdisplays_gpu".equals(deviceType.getAsString()))
continue;
JsonElement model = item.getAsJsonPrimitive("sppci_model");
JsonElement vendor = item.getAsJsonPrimitive("spdisplays_vendor");
JsonElement bus = item.getAsJsonPrimitive("sppci_bus");
if (model == null)
continue;
GraphicsCard.Builder builder = GraphicsCard.builder()
.setName(model.getAsString());
if (vendor != null)
builder.setVendor(GraphicsCard.Vendor.of(StringUtils.removePrefix(vendor.getAsString(), "sppci_vendor_")));
GraphicsCard.Type type = GraphicsCard.Type.Integrated;
if (bus != null) {
String lower = bus.getAsString().toLowerCase(Locale.ROOT);
if (!lower.contains("builtin") && !lower.contains("built_in") & !lower.contains("built-in"))
type = GraphicsCard.Type.Discrete;
}
builder.setType(type);
cards.add(builder.build());
}
return Collections.unmodifiableList(cards);
}
} catch (Throwable e) {
if (process != null && process.isAlive())
process.destroy();
LOG.warning("Failed to get graphics card info" + (json != null ? ": " + json : ""), e);
return Collections.emptyList();
}
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.windows;
/**
* @author Glavo
*/
public abstract class WinReg {
/**
* @see <a href="https://learn.microsoft.com/windows/win32/sysinfo/predefined-keys">Predefined Keys</a>
*/
public enum HKEY {
HKEY_CLASSES_ROOT(0x80000000),
HKEY_CURRENT_USER(0x80000001),
HKEY_LOCAL_MACHINE(0x80000002),
HKEY_USERS(0x80000003),
HKEY_PERFORMANCE_DATA(0x80000004),
HKEY_PERFORMANCE_TEXT(0x80000050),
HKEY_PERFORMANCE_NLSTEXT(0x80000060),
HKEY_CURRENT_CONFIG(0x80000005),
HKEY_DYN_DATA(0x80000006),
HKEY_CURRENT_USER_LOCAL_SETTINGS(0x80000007);
private final int value;
HKEY(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}

View File

@@ -0,0 +1,136 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.platform.windows;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard;
import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
/**
* @author Glavo
*/
public final class WindowsHardwareDetector extends HardwareDetector {
private static List<Map<String, String>> parsePowerShellFormatList(Iterable<String> lines) {
ArrayList<Map<String, String>> result = new ArrayList<>();
Map<String, String> current = new LinkedHashMap<>();
for (String line : lines) {
int idx = line.indexOf(':');
if (idx < 0) {
if (!current.isEmpty()) {
result.add(current);
current = new LinkedHashMap<>();
}
continue;
}
String key = line.substring(0, idx).trim();
String value = line.substring(idx + 1).trim();
current.put(key, value);
}
if (!current.isEmpty())
result.add(current);
return result;
}
@Override
public List<GraphicsCard> detectGraphicsCards() {
if (!OperatingSystem.isWindows7OrLater())
return null;
Process process = null;
String list = null;
try {
File nul = new File("NUL");
String getCimInstance = OperatingSystem.SYSTEM_VERSION.startsWith("6.1")
? "Get-WmiObject"
: "Get-CimInstance";
Process finalProcess = process = new ProcessBuilder("powershell.exe",
"-Command",
String.join(" | ",
getCimInstance + " -Class Win32_VideoController",
"Select-Object Name,AdapterCompatibility,DriverVersion,AdapterDACType",
"Format-List"
))
.redirectInput(nul)
.redirectError(nul)
.start();
CompletableFuture<String> future = CompletableFuture.supplyAsync(Lang.wrap(() ->
IOUtils.readFullyAsString(finalProcess.getInputStream(), OperatingSystem.NATIVE_CHARSET)),
Schedulers.io());
if (!process.waitFor(15, TimeUnit.SECONDS))
throw new TimeoutException();
if (process.exitValue() != 0)
throw new IOException("Bad exit code: " + process.exitValue());
list = future.get();
List<Map<String, String>> videoControllers = parsePowerShellFormatList(Arrays.asList(list.split("\\R")));
ArrayList<GraphicsCard> cards = new ArrayList<>(videoControllers.size());
for (Map<String, String> videoController : videoControllers) {
String name = videoController.get("Name");
String adapterCompatibility = videoController.get("AdapterCompatibility");
String driverVersion = videoController.get("DriverVersion");
String adapterDACType = videoController.get("AdapterDACType");
if (StringUtils.isNotBlank(name)) {
cards.add(GraphicsCard.builder().setName(name)
.setVendor(GraphicsCard.Vendor.of(adapterCompatibility))
.setDriverVersion(driverVersion)
.setType(StringUtils.isBlank(adapterDACType)
|| "Internal".equalsIgnoreCase(adapterDACType)
|| "InternalDAC".equalsIgnoreCase(adapterDACType)
? GraphicsCard.Type.Integrated
: GraphicsCard.Type.Discrete)
.build()
);
}
}
return cards;
} catch (Throwable e) {
if (process != null && process.isAlive())
process.destroy();
LOG.warning("Failed to get graphics card info" + (list != null ? ": " + list : ""), e);
return Collections.emptyList();
}
}
}

View File

@@ -0,0 +1,690 @@
# https://gitlab.freedesktop.org/mesa/drm/-/blob/b65d6ede3ebe64dbde5805007ddef22f390f8050/data/amdgpu.ids
#
# List of AMDGPU IDs
#
# Syntax:
# device_id, revision_id, product_name <-- single tab after comma
1.0.0
1114, C2, AMD Radeon 860M Graphics
1114, C3, AMD Radeon 840M Graphics
1114, D2, AMD Radeon 860M Graphics
1114, D3, AMD Radeon 840M Graphics
1309, 00, AMD Radeon R7 Graphics
130A, 00, AMD Radeon R6 Graphics
130B, 00, AMD Radeon R4 Graphics
130C, 00, AMD Radeon R7 Graphics
130D, 00, AMD Radeon R6 Graphics
130E, 00, AMD Radeon R5 Graphics
130F, 00, AMD Radeon R7 Graphics
130F, D4, AMD Radeon R7 Graphics
130F, D5, AMD Radeon R7 Graphics
130F, D6, AMD Radeon R7 Graphics
130F, D7, AMD Radeon R7 Graphics
1313, 00, AMD Radeon R7 Graphics
1313, D4, AMD Radeon R7 Graphics
1313, D5, AMD Radeon R7 Graphics
1313, D6, AMD Radeon R7 Graphics
1315, 00, AMD Radeon R5 Graphics
1315, D4, AMD Radeon R5 Graphics
1315, D5, AMD Radeon R5 Graphics
1315, D6, AMD Radeon R5 Graphics
1315, D7, AMD Radeon R5 Graphics
1316, 00, AMD Radeon R5 Graphics
1318, 00, AMD Radeon R5 Graphics
131B, 00, AMD Radeon R4 Graphics
131C, 00, AMD Radeon R7 Graphics
131D, 00, AMD Radeon R6 Graphics
1435, AE, AMD Custom GPU 0932
1506, C1, AMD Radeon 610M
1506, C2, AMD Radeon 610M
1506, C3, AMD Radeon 610M
1506, C4, AMD Radeon 610M
150E, C1, AMD Radeon 890M Graphics
150E, C4, AMD Radeon 890M Graphics
150E, C5, AMD Radeon 890M Graphics
150E, C6, AMD Radeon 890M Graphics
150E, D1, AMD Radeon 890M Graphics
150E, D2, AMD Radeon 890M Graphics
150E, D3, AMD Radeon 890M Graphics
1586, C1, Radeon 8060S Graphics
1586, C2, Radeon 8050S Graphics
1586, C4, Radeon 8050S Graphics
1586, D1, Radeon 8060S Graphics
1586, D2, Radeon 8050S Graphics
1586, D4, Radeon 8050S Graphics
1586, D5, Radeon 8040S Graphics
15BF, 00, AMD Radeon 780M Graphics
15BF, 01, AMD Radeon 760M Graphics
15BF, 02, AMD Radeon 780M Graphics
15BF, 03, AMD Radeon 760M Graphics
15BF, C1, AMD Radeon 780M Graphics
15BF, C2, AMD Radeon 780M Graphics
15BF, C3, AMD Radeon 760M Graphics
15BF, C4, AMD Radeon 780M Graphics
15BF, C5, AMD Radeon 740M Graphics
15BF, C6, AMD Radeon 780M Graphics
15BF, C7, AMD Radeon 780M Graphics
15BF, C8, AMD Radeon 760M Graphics
15BF, C9, AMD Radeon 780M Graphics
15BF, CA, AMD Radeon 740M Graphics
15BF, CB, AMD Radeon 760M Graphics
15BF, CC, AMD Radeon 740M Graphics
15BF, CD, AMD Radeon 760M Graphics
15BF, CF, AMD Radeon 780M Graphics
15BF, D0, AMD Radeon 780M Graphics
15BF, D1, AMD Radeon 780M Graphics
15BF, D2, AMD Radeon 780M Graphics
15BF, D3, AMD Radeon 780M Graphics
15BF, D4, AMD Radeon 780M Graphics
15BF, D5, AMD Radeon 760M Graphics
15BF, D6, AMD Radeon 760M Graphics
15BF, D7, AMD Radeon 780M Graphics
15BF, D8, AMD Radeon 740M Graphics
15BF, D9, AMD Radeon 780M Graphics
15BF, DA, AMD Radeon 780M Graphics
15BF, DB, AMD Radeon 760M Graphics
15BF, DC, AMD Radeon 760M Graphics
15BF, DD, AMD Radeon 780M Graphics
15BF, DE, AMD Radeon 740M Graphics
15BF, DF, AMD Radeon 760M Graphics
15BF, F0, AMD Radeon 760M Graphics
15C8, C1, AMD Radeon 740M Graphics
15C8, C2, AMD Radeon 740M Graphics
15C8, C3, AMD Radeon 740M Graphics
15C8, C4, AMD Radeon 740M Graphics
15C8, D1, AMD Radeon 740M Graphics
15C8, D2, AMD Radeon 740M Graphics
15C8, D3, AMD Radeon 740M Graphics
15C8, D4, AMD Radeon 740M Graphics
15D8, 00, AMD Radeon RX Vega 8 Graphics WS
15D8, 91, AMD Radeon Vega 3 Graphics
15D8, 91, AMD Ryzen Embedded R1606G with Radeon Vega Gfx
15D8, 92, AMD Radeon Vega 3 Graphics
15D8, 92, AMD Ryzen Embedded R1505G with Radeon Vega Gfx
15D8, 93, AMD Radeon Vega 1 Graphics
15D8, A1, AMD Radeon Vega 10 Graphics
15D8, A2, AMD Radeon Vega 8 Graphics
15D8, A3, AMD Radeon Vega 6 Graphics
15D8, A4, AMD Radeon Vega 3 Graphics
15D8, B1, AMD Radeon Vega 10 Graphics
15D8, B2, AMD Radeon Vega 8 Graphics
15D8, B3, AMD Radeon Vega 6 Graphics
15D8, B4, AMD Radeon Vega 3 Graphics
15D8, C1, AMD Radeon Vega 10 Graphics
15D8, C2, AMD Radeon Vega 8 Graphics
15D8, C3, AMD Radeon Vega 6 Graphics
15D8, C4, AMD Radeon Vega 3 Graphics
15D8, C5, AMD Radeon Vega 3 Graphics
15D8, C8, AMD Radeon Vega 11 Graphics
15D8, C9, AMD Radeon Vega 8 Graphics
15D8, CA, AMD Radeon Vega 11 Graphics
15D8, CB, AMD Radeon Vega 8 Graphics
15D8, CC, AMD Radeon Vega 3 Graphics
15D8, CE, AMD Radeon Vega 3 Graphics
15D8, CF, AMD Ryzen Embedded R1305G with Radeon Vega Gfx
15D8, D1, AMD Radeon Vega 10 Graphics
15D8, D2, AMD Radeon Vega 8 Graphics
15D8, D3, AMD Radeon Vega 6 Graphics
15D8, D4, AMD Radeon Vega 3 Graphics
15D8, D8, AMD Radeon Vega 11 Graphics
15D8, D9, AMD Radeon Vega 8 Graphics
15D8, DA, AMD Radeon Vega 11 Graphics
15D8, DB, AMD Radeon Vega 3 Graphics
15D8, DB, AMD Radeon Vega 8 Graphics
15D8, DC, AMD Radeon Vega 3 Graphics
15D8, DD, AMD Radeon Vega 3 Graphics
15D8, DE, AMD Radeon Vega 3 Graphics
15D8, DF, AMD Radeon Vega 3 Graphics
15D8, E3, AMD Radeon Vega 3 Graphics
15D8, E4, AMD Ryzen Embedded R1102G with Radeon Vega Gfx
15DD, 81, AMD Ryzen Embedded V1807B with Radeon Vega Gfx
15DD, 82, AMD Ryzen Embedded V1756B with Radeon Vega Gfx
15DD, 83, AMD Ryzen Embedded V1605B with Radeon Vega Gfx
15DD, 84, AMD Radeon Vega 6 Graphics
15DD, 85, AMD Ryzen Embedded V1202B with Radeon Vega Gfx
15DD, 86, AMD Radeon Vega 11 Graphics
15DD, 88, AMD Radeon Vega 8 Graphics
15DD, C1, AMD Radeon Vega 11 Graphics
15DD, C2, AMD Radeon Vega 8 Graphics
15DD, C3, AMD Radeon Vega 3 / 10 Graphics
15DD, C4, AMD Radeon Vega 8 Graphics
15DD, C5, AMD Radeon Vega 3 Graphics
15DD, C6, AMD Radeon Vega 11 Graphics
15DD, C8, AMD Radeon Vega 8 Graphics
15DD, C9, AMD Radeon Vega 11 Graphics
15DD, CA, AMD Radeon Vega 8 Graphics
15DD, CB, AMD Radeon Vega 3 Graphics
15DD, CC, AMD Radeon Vega 6 Graphics
15DD, CE, AMD Radeon Vega 3 Graphics
15DD, CF, AMD Radeon Vega 3 Graphics
15DD, D0, AMD Radeon Vega 10 Graphics
15DD, D1, AMD Radeon Vega 8 Graphics
15DD, D3, AMD Radeon Vega 11 Graphics
15DD, D5, AMD Radeon Vega 8 Graphics
15DD, D6, AMD Radeon Vega 11 Graphics
15DD, D7, AMD Radeon Vega 8 Graphics
15DD, D8, AMD Radeon Vega 3 Graphics
15DD, D9, AMD Radeon Vega 6 Graphics
15DD, E1, AMD Radeon Vega 3 Graphics
15DD, E2, AMD Radeon Vega 3 Graphics
163F, AE, AMD Custom GPU 0405
163F, E1, AMD Custom GPU 0405
164E, D8, AMD Radeon 610M
164E, D9, AMD Radeon 610M
164E, DA, AMD Radeon 610M
164E, DB, AMD Radeon 610M
164E, DC, AMD Radeon 610M
1681, 06, AMD Radeon 680M
1681, 07, AMD Radeon 660M
1681, 0A, AMD Radeon 680M
1681, 0B, AMD Radeon 660M
1681, C7, AMD Radeon 680M
1681, C8, AMD Radeon 680M
1681, C9, AMD Radeon 660M
1900, 01, AMD Radeon 780M Graphics
1900, 02, AMD Radeon 760M Graphics
1900, 03, AMD Radeon 780M Graphics
1900, 04, AMD Radeon 760M Graphics
1900, 05, AMD Radeon 780M Graphics
1900, 06, AMD Radeon 780M Graphics
1900, 07, AMD Radeon 760M Graphics
1900, B0, AMD Radeon 780M Graphics
1900, B1, AMD Radeon 780M Graphics
1900, B2, AMD Radeon 780M Graphics
1900, B3, AMD Radeon 780M Graphics
1900, B4, AMD Radeon 780M Graphics
1900, B5, AMD Radeon 780M Graphics
1900, B6, AMD Radeon 780M Graphics
1900, B7, AMD Radeon 760M Graphics
1900, B8, AMD Radeon 760M Graphics
1900, B9, AMD Radeon 780M Graphics
1900, BA, AMD Radeon 780M Graphics
1900, BB, AMD Radeon 780M Graphics
1900, C0, AMD Radeon 780M Graphics
1900, C1, AMD Radeon 760M Graphics
1900, C2, AMD Radeon 780M Graphics
1900, C3, AMD Radeon 760M Graphics
1900, C4, AMD Radeon 780M Graphics
1900, C5, AMD Radeon 780M Graphics
1900, C6, AMD Radeon 760M Graphics
1900, C7, AMD Radeon 780M Graphics
1900, C8, AMD Radeon 760M Graphics
1900, C9, AMD Radeon 780M Graphics
1900, CA, AMD Radeon 760M Graphics
1900, CB, AMD Radeon 780M Graphics
1900, CC, AMD Radeon 780M Graphics
1900, CD, AMD Radeon 760M Graphics
1900, CE, AMD Radeon 780M Graphics
1900, CF, AMD Radeon 760M Graphics
1900, D0, AMD Radeon 780M Graphics
1900, D1, AMD Radeon 760M Graphics
1900, D2, AMD Radeon 780M Graphics
1900, D3, AMD Radeon 760M Graphics
1900, D4, AMD Radeon 780M Graphics
1900, D5, AMD Radeon 780M Graphics
1900, D6, AMD Radeon 760M Graphics
1900, D7, AMD Radeon 780M Graphics
1900, D8, AMD Radeon 760M Graphics
1900, D9, AMD Radeon 780M Graphics
1900, DA, AMD Radeon 760M Graphics
1900, DB, AMD Radeon 780M Graphics
1900, DC, AMD Radeon 780M Graphics
1900, DD, AMD Radeon 760M Graphics
1900, DE, AMD Radeon 780M Graphics
1900, DF, AMD Radeon 760M Graphics
1900, F0, AMD Radeon 780M Graphics
1900, F1, AMD Radeon 780M Graphics
1900, F2, AMD Radeon 780M Graphics
1901, C1, AMD Radeon 740M Graphics
1901, C2, AMD Radeon 740M Graphics
1901, C3, AMD Radeon 740M Graphics
1901, C6, AMD Radeon 740M Graphics
1901, C7, AMD Radeon 740M Graphics
1901, C8, AMD Radeon 740M Graphics
1901, C9, AMD Radeon 740M Graphics
1901, CA, AMD Radeon 740M Graphics
1901, D1, AMD Radeon 740M Graphics
1901, D2, AMD Radeon 740M Graphics
1901, D3, AMD Radeon 740M Graphics
1901, D4, AMD Radeon 740M Graphics
1901, D5, AMD Radeon 740M Graphics
1901, D6, AMD Radeon 740M Graphics
1901, D7, AMD Radeon 740M Graphics
1901, D8, AMD Radeon 740M Graphics
6600, 00, AMD Radeon HD 8600 / 8700M
6600, 81, AMD Radeon R7 M370
6601, 00, AMD Radeon HD 8500M / 8700M
6604, 00, AMD Radeon R7 M265 Series
6604, 81, AMD Radeon R7 M350
6605, 00, AMD Radeon R7 M260 Series
6605, 81, AMD Radeon R7 M340
6606, 00, AMD Radeon HD 8790M
6607, 00, AMD Radeon R5 M240
6608, 00, AMD FirePro W2100
6610, 00, AMD Radeon R7 200 Series
6610, 81, AMD Radeon R7 350
6610, 83, AMD Radeon R5 340
6610, 87, AMD Radeon R7 200 Series
6611, 00, AMD Radeon R7 200 Series
6611, 87, AMD Radeon R7 200 Series
6613, 00, AMD Radeon R7 200 Series
6617, 00, AMD Radeon R7 240 Series
6617, 87, AMD Radeon R7 200 Series
6617, C7, AMD Radeon R7 240 Series
6640, 00, AMD Radeon HD 8950
6640, 80, AMD Radeon R9 M380
6646, 00, AMD Radeon R9 M280X
6646, 80, AMD Radeon R9 M385
6646, 80, AMD Radeon R9 M470X
6647, 00, AMD Radeon R9 M200X Series
6647, 80, AMD Radeon R9 M380
6649, 00, AMD FirePro W5100
6658, 00, AMD Radeon R7 200 Series
665C, 00, AMD Radeon HD 7700 Series
665D, 00, AMD Radeon R7 200 Series
665F, 81, AMD Radeon R7 360 Series
6660, 00, AMD Radeon HD 8600M Series
6660, 81, AMD Radeon R5 M335
6660, 83, AMD Radeon R5 M330
6663, 00, AMD Radeon HD 8500M Series
6663, 83, AMD Radeon R5 M320
6664, 00, AMD Radeon R5 M200 Series
6665, 00, AMD Radeon R5 M230 Series
6665, 83, AMD Radeon R5 M320
6665, C3, AMD Radeon R5 M435
6666, 00, AMD Radeon R5 M200 Series
6667, 00, AMD Radeon R5 M200 Series
666F, 00, AMD Radeon HD 8500M
66A1, 02, AMD Instinct MI60 / MI50
66A1, 06, AMD Radeon Pro VII
66AF, C1, AMD Radeon VII
6780, 00, AMD FirePro W9000
6784, 00, ATI FirePro V (FireGL V) Graphics Adapter
6788, 00, ATI FirePro V (FireGL V) Graphics Adapter
678A, 00, AMD FirePro W8000
6798, 00, AMD Radeon R9 200 / HD 7900 Series
6799, 00, AMD Radeon HD 7900 Series
679A, 00, AMD Radeon HD 7900 Series
679B, 00, AMD Radeon HD 7900 Series
679E, 00, AMD Radeon HD 7800 Series
67A0, 00, AMD Radeon FirePro W9100
67A1, 00, AMD Radeon FirePro W8100
67B0, 00, AMD Radeon R9 200 Series
67B0, 80, AMD Radeon R9 390 Series
67B1, 00, AMD Radeon R9 200 Series
67B1, 80, AMD Radeon R9 390 Series
67B9, 00, AMD Radeon R9 200 Series
67C0, 00, AMD Radeon Pro WX 7100 Graphics
67C0, 80, AMD Radeon E9550
67C2, 01, AMD Radeon Pro V7350x2
67C2, 02, AMD Radeon Pro V7300X
67C4, 00, AMD Radeon Pro WX 7100 Graphics
67C4, 80, AMD Radeon E9560 / E9565 Graphics
67C7, 00, AMD Radeon Pro WX 5100 Graphics
67C7, 80, AMD Radeon E9390 Graphics
67D0, 01, AMD Radeon Pro V7350x2
67D0, 02, AMD Radeon Pro V7300X
67DF, C0, AMD Radeon Pro 580X
67DF, C1, AMD Radeon RX 580 Series
67DF, C2, AMD Radeon RX 570 Series
67DF, C3, AMD Radeon RX 580 Series
67DF, C4, AMD Radeon RX 480 Graphics
67DF, C5, AMD Radeon RX 470 Graphics
67DF, C6, AMD Radeon RX 570 Series
67DF, C7, AMD Radeon RX 480 Graphics
67DF, CF, AMD Radeon RX 470 Graphics
67DF, D7, AMD Radeon RX 470 Graphics
67DF, E0, AMD Radeon RX 470 Series
67DF, E1, AMD Radeon RX 590 Series
67DF, E3, AMD Radeon RX Series
67DF, E7, AMD Radeon RX 580 Series
67DF, EB, AMD Radeon Pro 580X
67DF, EF, AMD Radeon RX 570 Series
67DF, F7, AMD Radeon RX P30PH
67DF, FF, AMD Radeon RX 470 Series
67E0, 00, AMD Radeon Pro WX Series
67E3, 00, AMD Radeon Pro WX 4100
67E8, 00, AMD Radeon Pro WX Series
67E8, 01, AMD Radeon Pro WX Series
67E8, 80, AMD Radeon E9260 Graphics
67EB, 00, AMD Radeon Pro V5300X
67EF, C0, AMD Radeon RX Graphics
67EF, C1, AMD Radeon RX 460 Graphics
67EF, C2, AMD Radeon Pro Series
67EF, C3, AMD Radeon RX Series
67EF, C5, AMD Radeon RX 460 Graphics
67EF, C7, AMD Radeon RX Graphics
67EF, CF, AMD Radeon RX 460 Graphics
67EF, E0, AMD Radeon RX 560 Series
67EF, E1, AMD Radeon RX Series
67EF, E2, AMD Radeon RX 560X
67EF, E3, AMD Radeon RX Series
67EF, E5, AMD Radeon RX 560 Series
67EF, E7, AMD Radeon RX 560 Series
67EF, EF, AMD Radeon 550 Series
67EF, FF, AMD Radeon RX 460 Graphics
67FF, C0, AMD Radeon Pro 465
67FF, C1, AMD Radeon RX 560 Series
67FF, CF, AMD Radeon RX 560 Series
67FF, EF, AMD Radeon RX 560 Series
67FF, FF, AMD Radeon RX 550 Series
6800, 00, AMD Radeon HD 7970M
6801, 00, AMD Radeon HD 8970M
6806, 00, AMD Radeon R9 M290X
6808, 00, AMD FirePro W7000
6808, 00, ATI FirePro V (FireGL V) Graphics Adapter
6809, 00, ATI FirePro W5000
6810, 00, AMD Radeon R9 200 Series
6810, 81, AMD Radeon R9 370 Series
6811, 00, AMD Radeon R9 200 Series
6811, 81, AMD Radeon R7 370 Series
6818, 00, AMD Radeon HD 7800 Series
6819, 00, AMD Radeon HD 7800 Series
6820, 00, AMD Radeon R9 M275X
6820, 81, AMD Radeon R9 M375
6820, 83, AMD Radeon R9 M375X
6821, 00, AMD Radeon R9 M200X Series
6821, 83, AMD Radeon R9 M370X
6821, 87, AMD Radeon R7 M380
6822, 00, AMD Radeon E8860
6823, 00, AMD Radeon R9 M200X Series
6825, 00, AMD Radeon HD 7800M Series
6826, 00, AMD Radeon HD 7700M Series
6827, 00, AMD Radeon HD 7800M Series
6828, 00, AMD FirePro W600
682B, 00, AMD Radeon HD 8800M Series
682B, 87, AMD Radeon R9 M360
682C, 00, AMD FirePro W4100
682D, 00, AMD Radeon HD 7700M Series
682F, 00, AMD Radeon HD 7700M Series
6830, 00, AMD Radeon 7800M Series
6831, 00, AMD Radeon 7700M Series
6835, 00, AMD Radeon R7 Series / HD 9000 Series
6837, 00, AMD Radeon HD 7700 Series
683D, 00, AMD Radeon HD 7700 Series
683F, 00, AMD Radeon HD 7700 Series
684C, 00, ATI FirePro V (FireGL V) Graphics Adapter
6860, 00, AMD Radeon Instinct MI25
6860, 01, AMD Radeon Instinct MI25
6860, 02, AMD Radeon Instinct MI25
6860, 03, AMD Radeon Pro V340
6860, 04, AMD Radeon Instinct MI25x2
6860, 07, AMD Radeon Pro V320
6861, 00, AMD Radeon Pro WX 9100
6862, 00, AMD Radeon Pro SSG
6863, 00, AMD Radeon Vega Frontier Edition
6864, 03, AMD Radeon Pro V340
6864, 04, AMD Radeon Instinct MI25x2
6864, 05, AMD Radeon Pro V340
6868, 00, AMD Radeon Pro WX 8200
686C, 00, AMD Radeon Instinct MI25 MxGPU
686C, 01, AMD Radeon Instinct MI25 MxGPU
686C, 02, AMD Radeon Instinct MI25 MxGPU
686C, 03, AMD Radeon Pro V340 MxGPU
686C, 04, AMD Radeon Instinct MI25x2 MxGPU
686C, 05, AMD Radeon Pro V340L MxGPU
686C, 06, AMD Radeon Instinct MI25 MxGPU
687F, 01, AMD Radeon RX Vega
687F, C0, AMD Radeon RX Vega
687F, C1, AMD Radeon RX Vega
687F, C3, AMD Radeon RX Vega
687F, C7, AMD Radeon RX Vega
6900, 00, AMD Radeon R7 M260
6900, 81, AMD Radeon R7 M360
6900, 83, AMD Radeon R7 M340
6900, C1, AMD Radeon R5 M465 Series
6900, C3, AMD Radeon R5 M445 Series
6900, D1, AMD Radeon 530 Series
6900, D3, AMD Radeon 530 Series
6901, 00, AMD Radeon R5 M255
6902, 00, AMD Radeon Series
6907, 00, AMD Radeon R5 M255
6907, 87, AMD Radeon R5 M315
6920, 00, AMD Radeon R9 M395X
6920, 01, AMD Radeon R9 M390X
6921, 00, AMD Radeon R9 M390X
6929, 00, AMD FirePro S7150
6929, 01, AMD FirePro S7100X
692B, 00, AMD FirePro W7100
6938, 00, AMD Radeon R9 200 Series
6938, F0, AMD Radeon R9 200 Series
6938, F1, AMD Radeon R9 380 Series
6939, 00, AMD Radeon R9 200 Series
6939, F0, AMD Radeon R9 200 Series
6939, F1, AMD Radeon R9 380 Series
694C, C0, AMD Radeon RX Vega M GH Graphics
694E, C0, AMD Radeon RX Vega M GL Graphics
6980, 00, AMD Radeon Pro WX 3100
6981, 00, AMD Radeon Pro WX 3200 Series
6981, 01, AMD Radeon Pro WX 3200 Series
6981, 10, AMD Radeon Pro WX 3200 Series
6985, 00, AMD Radeon Pro WX 3100
6986, 00, AMD Radeon Pro WX 2100
6987, 80, AMD Embedded Radeon E9171
6987, C0, AMD Radeon 550X Series
6987, C1, AMD Radeon RX 640
6987, C3, AMD Radeon 540X Series
6987, C7, AMD Radeon 540
6995, 00, AMD Radeon Pro WX 2100
6997, 00, AMD Radeon Pro WX 2100
699F, 81, AMD Embedded Radeon E9170 Series
699F, C0, AMD Radeon 500 Series
699F, C1, AMD Radeon 540 Series
699F, C3, AMD Radeon 500 Series
699F, C7, AMD Radeon RX 550 / 550 Series
699F, C9, AMD Radeon 540
6FDF, E7, AMD Radeon RX 590 GME
6FDF, EF, AMD Radeon RX 580 2048SP
7300, C1, AMD FirePro S9300 x2
7300, C8, AMD Radeon R9 Fury Series
7300, C9, AMD Radeon Pro Duo
7300, CA, AMD Radeon R9 Fury Series
7300, CB, AMD Radeon R9 Fury Series
7312, 00, AMD Radeon Pro W5700
731E, C6, AMD Radeon RX 5700XTB
731E, C7, AMD Radeon RX 5700B
731F, C0, AMD Radeon RX 5700 XT 50th Anniversary
731F, C1, AMD Radeon RX 5700 XT
731F, C2, AMD Radeon RX 5600M
731F, C3, AMD Radeon RX 5700M
731F, C4, AMD Radeon RX 5700
731F, C5, AMD Radeon RX 5700 XT
731F, CA, AMD Radeon RX 5600 XT
731F, CB, AMD Radeon RX 5600 OEM
7340, C1, AMD Radeon RX 5500M
7340, C3, AMD Radeon RX 5300M
7340, C5, AMD Radeon RX 5500 XT
7340, C7, AMD Radeon RX 5500
7340, C9, AMD Radeon RX 5500XTB
7340, CF, AMD Radeon RX 5300
7341, 00, AMD Radeon Pro W5500
7347, 00, AMD Radeon Pro W5500M
7360, 41, AMD Radeon Pro 5600M
7360, C3, AMD Radeon Pro V520
7362, C1, AMD Radeon Pro V540
7362, C3, AMD Radeon Pro V520
738C, 01, AMD Instinct MI100
73A1, 00, AMD Radeon Pro V620
73A3, 00, AMD Radeon Pro W6800
73A5, C0, AMD Radeon RX 6950 XT
73AE, 00, AMD Radeon Pro V620 MxGPU
73AF, C0, AMD Radeon RX 6900 XT
73BF, C0, AMD Radeon RX 6900 XT
73BF, C1, AMD Radeon RX 6800 XT
73BF, C3, AMD Radeon RX 6800
73DF, C0, AMD Radeon RX 6750 XT
73DF, C1, AMD Radeon RX 6700 XT
73DF, C2, AMD Radeon RX 6800M
73DF, C3, AMD Radeon RX 6800M
73DF, C5, AMD Radeon RX 6700 XT
73DF, CF, AMD Radeon RX 6700M
73DF, D5, AMD Radeon RX 6750 GRE 12GB
73DF, D7, AMD TDC-235
73DF, DF, AMD Radeon RX 6700
73DF, E5, AMD Radeon RX 6750 GRE 12GB
73DF, FF, AMD Radeon RX 6700
73E0, 00, AMD Radeon RX 6600M
73E1, 00, AMD Radeon Pro W6600M
73E3, 00, AMD Radeon Pro W6600
73EF, C0, AMD Radeon RX 6800S
73EF, C1, AMD Radeon RX 6650 XT
73EF, C2, AMD Radeon RX 6700S
73EF, C3, AMD Radeon RX 6650M
73EF, C4, AMD Radeon RX 6650M XT
73FF, C1, AMD Radeon RX 6600 XT
73FF, C3, AMD Radeon RX 6600M
73FF, C7, AMD Radeon RX 6600
73FF, CB, AMD Radeon RX 6600S
73FF, CF, AMD Radeon RX 6600 LE
73FF, DF, AMD Radeon RX 6750 GRE 10GB
7408, 00, AMD Instinct MI250X
740C, 01, AMD Instinct MI250X / MI250
740F, 02, AMD Instinct MI210
7421, 00, AMD Radeon Pro W6500M
7422, 00, AMD Radeon Pro W6400
7423, 00, AMD Radeon Pro W6300M
7423, 01, AMD Radeon Pro W6300
7424, 00, AMD Radeon RX 6300
743F, C1, AMD Radeon RX 6500 XT
743F, C3, AMD Radeon RX 6500
743F, C3, AMD Radeon RX 6500M
743F, C7, AMD Radeon RX 6400
743F, C8, AMD Radeon RX 6500M
743F, CC, AMD Radeon 6550S
743F, CE, AMD Radeon RX 6450M
743F, CF, AMD Radeon RX 6300M
743F, D3, AMD Radeon RX 6550M
743F, D7, AMD Radeon RX 6400
7448, 00, AMD Radeon Pro W7900
7449, 00, AMD Radeon Pro W7800 48GB
744A, 00, AMD Radeon Pro W7900 Dual Slot
744C, C8, AMD Radeon RX 7900 XTX
744C, CC, AMD Radeon RX 7900 XT
744C, CE, AMD Radeon RX 7900 GRE
744C, CF, AMD Radeon RX 7900M
745E, CC, AMD Radeon Pro W7800
7460, 00, AMD Radeon Pro V710
7461, 00, AMD Radeon Pro V710 MxGPU
7470, 00, AMD Radeon Pro W7700
747E, C8, AMD Radeon RX 7800 XT
747E, D8, AMD Radeon RX 7800M
747E, FF, AMD Radeon RX 7700 XT
7480, 00, AMD Radeon Pro W7600
7480, C0, AMD Radeon RX 7600 XT
7480, C1, AMD Radeon RX 7700S
7480, C2, AMD Radeon RX 7650 GRE
7480, C3, AMD Radeon RX 7600S
7480, C7, AMD Radeon RX 7600M XT
7480, CF, AMD Radeon RX 7600
7483, CF, AMD Radeon RX 7600M
7489, 00, AMD Radeon Pro W7500
7499, 00, AMD Radeon Pro W7400
7499, C0, AMD Radeon RX 7400
7499, C1, AMD Radeon RX 7300
74A0, 00, AMD Instinct MI300A
74A1, 00, AMD Instinct MI300X
74A2, 00, AMD Instinct MI308X
74A5, 00, AMD Instinct MI325X
74A9, 00, AMD Instinct MI300X HF
74B5, 00, AMD Instinct MI300X VF
74B6, 00, AMD Instinct MI308X
74BD, 00, AMD Instinct MI300X HF
7550, C0, AMD Radeon RX 9070 XT
7550, C3, AMD Radeon RX 9070
9830, 00, AMD Radeon HD 8400 / R3 Series
9831, 00, AMD Radeon HD 8400E
9832, 00, AMD Radeon HD 8330
9833, 00, AMD Radeon HD 8330E
9834, 00, AMD Radeon HD 8210
9835, 00, AMD Radeon HD 8210E
9836, 00, AMD Radeon HD 8200 / R3 Series
9837, 00, AMD Radeon HD 8280E
9838, 00, AMD Radeon HD 8200 / R3 series
9839, 00, AMD Radeon HD 8180
983D, 00, AMD Radeon HD 8250
9850, 00, AMD Radeon R3 Graphics
9850, 03, AMD Radeon R3 Graphics
9850, 40, AMD Radeon R2 Graphics
9850, 45, AMD Radeon R3 Graphics
9851, 00, AMD Radeon R4 Graphics
9851, 01, AMD Radeon R5E Graphics
9851, 05, AMD Radeon R5 Graphics
9851, 06, AMD Radeon R5E Graphics
9851, 40, AMD Radeon R4 Graphics
9851, 45, AMD Radeon R5 Graphics
9852, 00, AMD Radeon R2 Graphics
9852, 40, AMD Radeon E1 Graphics
9853, 00, AMD Radeon R2 Graphics
9853, 01, AMD Radeon R4E Graphics
9853, 03, AMD Radeon R2 Graphics
9853, 05, AMD Radeon R1E Graphics
9853, 06, AMD Radeon R1E Graphics
9853, 07, AMD Radeon R1E Graphics
9853, 08, AMD Radeon R1E Graphics
9853, 40, AMD Radeon R2 Graphics
9854, 00, AMD Radeon R3 Graphics
9854, 01, AMD Radeon R3E Graphics
9854, 02, AMD Radeon R3 Graphics
9854, 05, AMD Radeon R2 Graphics
9854, 06, AMD Radeon R4 Graphics
9854, 07, AMD Radeon R3 Graphics
9855, 02, AMD Radeon R6 Graphics
9855, 05, AMD Radeon R4 Graphics
9856, 00, AMD Radeon R2 Graphics
9856, 01, AMD Radeon R2E Graphics
9856, 02, AMD Radeon R2 Graphics
9856, 05, AMD Radeon R1E Graphics
9856, 06, AMD Radeon R2 Graphics
9856, 07, AMD Radeon R1E Graphics
9856, 08, AMD Radeon R1E Graphics
9856, 13, AMD Radeon R1E Graphics
9874, 81, AMD Radeon R6 Graphics
9874, 84, AMD Radeon R7 Graphics
9874, 85, AMD Radeon R6 Graphics
9874, 87, AMD Radeon R5 Graphics
9874, 88, AMD Radeon R7E Graphics
9874, 89, AMD Radeon R6E Graphics
9874, C4, AMD Radeon R7 Graphics
9874, C5, AMD Radeon R6 Graphics
9874, C6, AMD Radeon R6 Graphics
9874, C7, AMD Radeon R5 Graphics
9874, C8, AMD Radeon R7 Graphics
9874, C9, AMD Radeon R7 Graphics
9874, CA, AMD Radeon R5 Graphics
9874, CB, AMD Radeon R5 Graphics
9874, CC, AMD Radeon R7 Graphics
9874, CD, AMD Radeon R7 Graphics
9874, CE, AMD Radeon R5 Graphics
9874, E1, AMD Radeon R7 Graphics
9874, E2, AMD Radeon R7 Graphics
9874, E3, AMD Radeon R7 Graphics
9874, E4, AMD Radeon R7 Graphics
9874, E5, AMD Radeon R5 Graphics
9874, E6, AMD Radeon R5 Graphics
98E4, 80, AMD Radeon R5E Graphics
98E4, 81, AMD Radeon R4E Graphics
98E4, 83, AMD Radeon R2E Graphics
98E4, 84, AMD Radeon R2E Graphics
98E4, 86, AMD Radeon R1E Graphics
98E4, C0, AMD Radeon R4 Graphics
98E4, C1, AMD Radeon R5 Graphics
98E4, C2, AMD Radeon R4 Graphics
98E4, C4, AMD Radeon R5 Graphics
98E4, C6, AMD Radeon R5 Graphics
98E4, C8, AMD Radeon R4 Graphics
98E4, C9, AMD Radeon R4 Graphics
98E4, CA, AMD Radeon R5 Graphics
98E4, D0, AMD Radeon R2 Graphics
98E4, D1, AMD Radeon R2 Graphics
98E4, D2, AMD Radeon R2 Graphics
98E4, D4, AMD Radeon R2 Graphics
98E4, D9, AMD Radeon R5 Graphics
98E4, DA, AMD Radeon R5 Graphics
98E4, DB, AMD Radeon R3 Graphics
98E4, E1, AMD Radeon R3 Graphics
98E4, E2, AMD Radeon R3 Graphics
98E4, E9, AMD Radeon R4 Graphics
98E4, EA, AMD Radeon R4 Graphics
98E4, EB, AMD Radeon R3 Graphics
98E4, EB, AMD Radeon R4 Graphics

View File

@@ -0,0 +1,68 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2025 huangyuhui <huanghongxun2008@126.com> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util.io;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Glavo
*/
public final class CSVTableTest {
@Test
public void testCreate() {
CSVTable table = new CSVTable();
assertEquals(0, table.getColumnCount());
assertEquals(0, table.getRowCount());
table.set(0, 0, "test1");
assertEquals(1, table.getColumnCount());
assertEquals(1, table.getRowCount());
table.set(4, 0, "test2");
assertEquals(5, table.getColumnCount());
assertEquals(1, table.getRowCount());
table.set(2, 1, "test3");
assertEquals(5, table.getColumnCount());
assertEquals(2, table.getRowCount());
assertEquals("test1", table.get(0, 0));
assertEquals("", table.get(1, 0));
assertEquals("", table.get(0, 1));
assertEquals("test2", table.get(4, 0));
assertEquals("test3", table.get(2, 1));
}
@Test
public void testToString() {
CSVTable table = new CSVTable();
table.set(0, 0, "a");
table.set(1, 0, "b");
table.set(3, 0, "c");
table.set(0, 2, "a,b");
table.set(1, 2, "c");
table.set(3, 2, "d\"e\n");
assertEquals("a,b,,c\n,,,\n\"a,b\",c,,\"d\\\"e\\n\"\n", table.toString());
}
}

View File

@@ -13,6 +13,7 @@ jsoup = "1.19.1"
chardet = "2.5.0"
twelvemonkeys = "3.12.0"
jna = "5.17.0"
pci-ids = "0.4.0"
# plugins
shadow = "8.3.6"
@@ -33,6 +34,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
chardet = { module = "org.glavo:chardet", version.ref = "chardet" }
twelvemonkeys-imageio-webp = { module = "com.twelvemonkeys.imageio:imageio-webp", version.ref = "twelvemonkeys" }
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
pci-ids = { module = "org.glavo:pci-ids", version.ref = "pci-ids" }
[plugins]
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }