mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2026-10-16 21:21:33 +08:00
@@ -50,6 +50,7 @@ import org.jackhuang.hmcl.util.i18n.I18n;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.ResponseCodeException;
|
||||
import org.jackhuang.hmcl.util.platform.*;
|
||||
import org.jackhuang.hmcl.util.platform.windows.WinReg;
|
||||
import org.jackhuang.hmcl.util.versioning.GameVersionNumber;
|
||||
import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -242,6 +243,36 @@ public final class LauncherHelper {
|
||||
launchOptionsBuilder.setQuickPlayOption(quickPlayOption);
|
||||
}
|
||||
|
||||
if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS && setting.getInheritable(GameSettings::highPerformanceProperty)) {
|
||||
@Nullable String javaPathGpuReg = FileUtils.getAbsolutePath(javaVersionRef.get().getBinary());
|
||||
try {
|
||||
WinReg reg = WinReg.INSTANCE;
|
||||
if (reg != null) {
|
||||
Object current = reg.queryValue(
|
||||
WinReg.HKEY.HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\DirectX\\UserGpuPreferences",
|
||||
javaPathGpuReg
|
||||
);
|
||||
if (current == null) {
|
||||
boolean result = reg.setValue(
|
||||
WinReg.HKEY.HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\DirectX\\UserGpuPreferences",
|
||||
javaPathGpuReg,
|
||||
"GpuPreference=2;"
|
||||
);
|
||||
if (result)
|
||||
LOG.info("Successfully applied high performance GPU preference for java: " + javaPathGpuReg);
|
||||
else
|
||||
LOG.warning("Failed to apply high performance GPU preference for java: " + javaPathGpuReg);
|
||||
} else {
|
||||
LOG.info("GPU preference for %s already exists: %s".formatted(javaPathGpuReg, current));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warning("Failed to apply high performance GPU preference", e);
|
||||
}
|
||||
}
|
||||
|
||||
LaunchOptions launchOptions = launchOptionsBuilder.create();
|
||||
|
||||
LOG.info("Here's the structure of game mod directory:\n" + FileUtils.printFileStructure(repository.getModsDirectory(selectedInstanceId), 10));
|
||||
|
||||
@@ -643,6 +643,19 @@ public sealed abstract class GameSettings extends ObservableSetting {
|
||||
return vulkanRenderer;
|
||||
}
|
||||
|
||||
/// Property name for high performance GPU preference.
|
||||
public static final String PROPERTY_HIGH_PERFORMANCE = "highPerformance";
|
||||
|
||||
/// Whether to launch games with high-performance GPU.
|
||||
@SerializedName(PROPERTY_HIGH_PERFORMANCE)
|
||||
private final InheritableProperty<Boolean> highPerformance =
|
||||
newInheritableProperty(PROPERTY_HIGH_PERFORMANCE, false);
|
||||
|
||||
/// Returns the high performance GPU preference property.
|
||||
public InheritableProperty<Boolean> highPerformanceProperty() {
|
||||
return highPerformance;
|
||||
}
|
||||
|
||||
/// Property name for customized environment variables.
|
||||
public static final String PROPERTY_ENVIRONMENT_VARIABLES = "environmentVariables";
|
||||
|
||||
|
||||
@@ -787,6 +787,11 @@ public final class GameSettingsPage<S extends GameSettings> extends StackPane
|
||||
graphicsSettings.getContent().add(vulkanRendererPane);
|
||||
vulkanRendererPane.setTitle(i18n("settings.advanced.renderer.vulkan"));
|
||||
|
||||
var highPerformancePane = createInheritableBooleanButton(GameSettings::highPerformanceProperty);
|
||||
graphicsSettings.getContent().add(highPerformancePane);
|
||||
highPerformancePane.setTitle(i18n("settings.advanced.renderer.gpu_preferences"));
|
||||
highPerformancePane.setSubtitle(i18n("settings.advanced.windows_only"));
|
||||
|
||||
this.currentGameVersionNumber.addListener((o, oldValue, newValue) -> {
|
||||
boolean showBackendChoose = isPresetSetting || newValue.compareTo("26.2-snapshot-2") >= 0;
|
||||
graphicsBackendPane.setVisible(showBackendChoose);
|
||||
|
||||
@@ -1489,6 +1489,7 @@ settings.advanced.renderer.default=Default
|
||||
settings.advanced.renderer.default.desc=Use System Default
|
||||
settings.advanced.renderer.opengl=OpenGL Renderer/Driver
|
||||
settings.advanced.renderer.vulkan=Vulkan Renderer/Driver
|
||||
settings.advanced.renderer.gpu_preferences=Launch games with high-performance GPU
|
||||
# Vulkan Renderers
|
||||
settings.advanced.renderer.lavapipe=Mesa Lavapipe
|
||||
settings.advanced.renderer.lavapipe.desc=Software Vulkan Renderer
|
||||
@@ -1535,6 +1536,7 @@ settings.advanced.unsupported_system_options=Settings not applicable to the curr
|
||||
settings.advanced.use_native_glfw=Use System GLFW
|
||||
settings.advanced.use_native_openal=Use System OpenAL
|
||||
settings.advanced.linux_freebsd_only=Linux/FreeBSD Only
|
||||
settings.advanced.windows_only=Windows Only
|
||||
settings.advanced.workaround=Workaround
|
||||
settings.advanced.workaround.warning=Workaround options are intended only for advanced users. Tweaking with these options may crash the game. Unless you know what you are doing, please do not edit these options.
|
||||
settings.advanced.wrapper_launcher=Wrapper Command
|
||||
|
||||
@@ -1292,6 +1292,7 @@ settings.advanced.renderer.default=預設
|
||||
settings.advanced.renderer.default.desc=使用系統預設繪製器
|
||||
settings.advanced.renderer.opengl=OpenGL 繪製器/驅動
|
||||
settings.advanced.renderer.vulkan=Vulkan 繪製器/驅動
|
||||
settings.advanced.renderer.gpu_preferences=使用高效能 GPU 啟動遊戲
|
||||
# Vulkan Renderers
|
||||
settings.advanced.renderer.lavapipe=Mesa Lavapipe
|
||||
settings.advanced.renderer.lavapipe.desc=軟體 Vulkan 繪製器
|
||||
@@ -1338,6 +1339,7 @@ settings.advanced.unsupported_system_options=不適用於目前系統的選項
|
||||
settings.advanced.use_native_glfw=使用系統 GLFW
|
||||
settings.advanced.use_native_openal=使用系統 OpenAL
|
||||
settings.advanced.linux_freebsd_only=僅限 Linux/FreeBSD
|
||||
settings.advanced.windows_only=僅限 Windows
|
||||
settings.advanced.workaround=除錯選項
|
||||
settings.advanced.workaround.warning=除錯選項僅提供給專業玩家使用。修改除錯選項可能會導致遊戲無法啟動。除非你知道你在做什麼,否則請不要修改這些選項。
|
||||
settings.advanced.wrapper_launcher=前置指令
|
||||
|
||||
@@ -1292,6 +1292,7 @@ settings.advanced.renderer.default=默认
|
||||
settings.advanced.renderer.default.desc=使用系统默认渲染器
|
||||
settings.advanced.renderer.opengl=OpenGL 渲染器/驱动
|
||||
settings.advanced.renderer.vulkan=Vulkan 渲染器/驱动
|
||||
settings.advanced.renderer.gpu_preferences=使用高性能 GPU 启动游戏
|
||||
# Vulkan Renderers
|
||||
settings.advanced.renderer.lavapipe=Mesa Lavapipe
|
||||
settings.advanced.renderer.lavapipe.desc=软件 Vulkan 渲染器
|
||||
@@ -1338,6 +1339,7 @@ settings.advanced.unsupported_system_options=不适用于当前系统的选项
|
||||
settings.advanced.use_native_glfw=使用系统 GLFW
|
||||
settings.advanced.use_native_openal=使用系统 OpenAL
|
||||
settings.advanced.linux_freebsd_only=仅 Linux/FreeBSD
|
||||
settings.advanced.windows_only=仅 Windows
|
||||
settings.advanced.workaround=调试选项
|
||||
settings.advanced.workaround.warning=调试选项仅提供给专业玩家使用。调试选项可能会导致游戏无法启动。除非你知道你在做什么,否则请不要修改这些选项!
|
||||
settings.advanced.wrapper_launcher=包装命令
|
||||
|
||||
@@ -56,4 +56,22 @@ public interface Advapi32 extends StdCallLibrary {
|
||||
IntByReference lpReserved,
|
||||
Pointer lpClass, IntByReference lpcchClass,
|
||||
Pointer lpftLastWriteTime);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regcreatekeyexw">RegCreateKeyExW function</a>
|
||||
*/
|
||||
int RegCreateKeyExW(Pointer hKey, WString lpSubKey, int Reserved, WString lpClass,
|
||||
int dwOptions, int samDesired, Pointer lpSecurityAttributes,
|
||||
PointerByReference phkResult, IntByReference lpdwDisposition);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regsetvalueexw">RegSetValueExW function</a>
|
||||
*/
|
||||
int RegSetValueExW(Pointer hKey, WString lpValueName, int Reserved, int dwType,
|
||||
Pointer lpData, int cbData);
|
||||
|
||||
/**
|
||||
* @see <a href="https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regdeletevaluew">RegDeleteValueW function</a>
|
||||
*/
|
||||
int RegDeleteValueW(Pointer hKey, WString lpValueName);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ public interface WinConstants {
|
||||
// https://learn.microsoft.com/windows/win32/sysinfo/registry-key-security-and-access-rights
|
||||
int KEY_QUERY_VALUE = 0x0001;
|
||||
int KEY_ENUMERATE_SUB_KEYS = 0x0008;
|
||||
int KEY_WRITE = 0x20006;
|
||||
int KEY_SET_VALUE = 0x0002;
|
||||
int KEY_READ = 0x20019;
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/sysinfo/registry-value-types
|
||||
@@ -114,4 +116,6 @@ public interface WinConstants {
|
||||
// https://learn.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
|
||||
int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
|
||||
// https://learn.microsoft.com/windows/win32/api/winreg/nf-winreg-regcreatekeyexw
|
||||
int REG_OPTION_NON_VOLATILE = 0x0000;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,10 @@ public abstract class WinReg {
|
||||
return list;
|
||||
}
|
||||
|
||||
public abstract boolean setValue(HKEY root, String key, String valueName, String value);
|
||||
|
||||
public abstract boolean deleteValue(HKEY root, String key, String valueName);
|
||||
|
||||
private static final class JNAWinReg extends WinReg {
|
||||
|
||||
private final Advapi32 advapi32;
|
||||
@@ -245,6 +249,63 @@ public abstract class WinReg {
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setValue(HKEY root, String key, String valueName, String value) {
|
||||
PointerByReference phkKey = new PointerByReference();
|
||||
int status = advapi32.RegCreateKeyExW(
|
||||
root.toPointer(),
|
||||
new WString(key),
|
||||
0,
|
||||
null,
|
||||
WinConstants.REG_OPTION_NON_VOLATILE,
|
||||
WinConstants.KEY_WRITE,
|
||||
null,
|
||||
phkKey,
|
||||
null
|
||||
);
|
||||
|
||||
if (status != WinConstants.ERROR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Pointer hkey = phkKey.getValue();
|
||||
try {
|
||||
byte[] data = (value + "\0").getBytes(StandardCharsets.UTF_16LE);
|
||||
try (Memory mem = new Memory(data.length)) {
|
||||
mem.write(0, data, 0, data.length);
|
||||
status = advapi32.RegSetValueExW(
|
||||
hkey,
|
||||
new WString(valueName),
|
||||
0,
|
||||
WinConstants.REG_SZ,
|
||||
mem,
|
||||
data.length
|
||||
);
|
||||
}
|
||||
return status == WinConstants.ERROR_SUCCESS;
|
||||
} finally {
|
||||
advapi32.RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteValue(HKEY root, String key, String valueName) {
|
||||
PointerByReference phkKey = new PointerByReference();
|
||||
int status = advapi32.RegOpenKeyExW(root.toPointer(), new WString(key), 0, WinConstants.KEY_SET_VALUE, phkKey);
|
||||
|
||||
if (status != WinConstants.ERROR_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Pointer hkey = phkKey.getValue();
|
||||
try {
|
||||
status = advapi32.RegDeleteValueW(hkey, new WString(valueName));
|
||||
return status == WinConstants.ERROR_SUCCESS;
|
||||
} finally {
|
||||
advapi32.RegCloseKey(hkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user