Files
Hytale-F2P/backend/utils/platformUtils.js
Fazri Gading 905a9d754c Merge GPU preference feature branch to main branch version 2.0.2 for testing (#3)
* modernized UI for GPU Preference option

* feat: auto-detect dedicated GPU on hybrid laptops (iGPU+dGPU)

* feat: detailed GPU info in auto-detection feature on startup

* feat: add GPU options for launcher

- Add GPU preference setting (Auto/Integrated/Dedicated)
- Implement Linux GPU selection with DRI_PRIME and NVIDIA env vars
- Add GPU detection using Electron's app.getGPUInfo()
- Update settings UI with GPU preference dropdown
- Integrate GPU preference into game launch process

* feat: auto-detect dedicated GPU on hybrid laptops (iGPU+dGPU)

* added fallbacks to and option to use integrated GPU.

* add package-lock and fix deps version

* changed 'Nvidia' string to 'NVIDIA'

* fix: selecting `dedicated` option while using nvidia GPU did not set its specific env variables

* remove unused `CONFIG_FILE` variable on launcher core modules

* fix: duplicated save-load gpu detection functions

* move game option settings to the top, while custom java to the bottom

* fix: settings-header margin-bottom from 3rem to 1rem and supress line-clamp warning
2026-01-20 23:45:38 +08:00

165 lines
4.9 KiB
JavaScript

const { execSync } = require('child_process');
function getOS() {
if (process.platform === 'win32') return 'windows';
if (process.platform === 'darwin') return 'darwin';
if (process.platform === 'linux') return 'linux';
return 'unknown';
}
function getArch() {
return process.arch === 'x64' ? 'amd64' : process.arch;
}
function isWaylandSession() {
if (process.platform !== 'linux') {
return false;
}
const sessionType = process.env.XDG_SESSION_TYPE;
if (sessionType && sessionType.toLowerCase() === 'wayland') {
return true;
}
if (process.env.WAYLAND_DISPLAY) {
return true;
}
try {
const sessionId = process.env.XDG_SESSION_ID;
if (sessionId) {
const output = execSync(`loginctl show-session ${sessionId} -p Type`, { encoding: 'utf8' });
if (output && output.toLowerCase().includes('wayland')) {
return true;
}
}
} catch (err) {
}
return false;
}
function setupWaylandEnvironment() {
if (process.platform !== 'linux') {
return {};
}
if (!isWaylandSession()) {
console.log('Detected X11 session, using default environment');
return {};
}
console.log('Detected Wayland session, configuring environment...');
const envVars = {
SDL_VIDEODRIVER: 'wayland',
GDK_BACKEND: 'wayland',
QT_QPA_PLATFORM: 'wayland',
MOZ_ENABLE_WAYLAND: '1',
_JAVA_AWT_WM_NONREPARENTING: '1'
};
envVars.ELECTRON_OZONE_PLATFORM_HINT = 'wayland';
console.log('Wayland environment variables:', envVars);
return envVars;
}
function detectGpu() {
if (process.platform !== 'linux') {
return { mode: 'integrated', vendor: 'intel', integratedName: 'Unknown', dedicatedName: null };
}
try {
const output = execSync('lspci -nn | grep \'VGA\\|3D\'', { encoding: 'utf8' });
// console.log('GPU detection raw output:', output);
const lines = output.split('\n').filter(line => line.trim());
// console.log('GPU detection parsed lines:', lines);
let integratedName = null;
let dedicatedName = null;
let hasNvidia = false;
let hasAmd = false;
for (const line of lines) {
// console.log('Checking line:', line);
if (line.includes('VGA') || line.includes('3D')) {
// console.log('Line contains VGA or 3D');
const match = line.match(/\[([^\]]+)\]/g);
let modelName = null;
if (match && match.length >= 2) {
modelName = match[1].slice(1, -1);
}
if (line.includes('10de:') || line.toLowerCase().includes('nvidia')) {
hasNvidia = true;
dedicatedName = "NVIDIA " + modelName || 'NVIDIA GPU';
console.log('Detected NVIDIA GPU:', dedicatedName);
} else if (line.includes('1002:') || line.toLowerCase().includes('amd') || line.toLowerCase().includes('radeon')) {
hasAmd = true;
dedicatedName = "AMD " + modelName || 'AMD GPU';
console.log('Detected AMD GPU:', dedicatedName);
} else if (line.includes('8086:') || line.toLowerCase().includes('intel')) {
integratedName = "Intel " + modelName || 'Intel GPU';
console.log('Detected Intel GPU:', integratedName);
}
}
}
// console.log('hasNvidia:', hasNvidia, 'hasAmd:', hasAmd, 'integratedName:', integratedName, 'dedicatedName:', dedicatedName);
if (hasNvidia) {
return { mode: 'dedicated', vendor: 'nvidia', integratedName: integratedName || 'Intel GPU', dedicatedName };
} else if (hasAmd) {
return { mode: 'dedicated', vendor: 'amd', integratedName: integratedName || 'Intel GPU', dedicatedName };
} else {
return { mode: 'integrated', vendor: 'intel', integratedName: integratedName || 'Intel GPU', dedicatedName: null };
}
} catch (error) {
console.warn('GPU detection failed, falling back to integrated:', error.message);
return { mode: 'integrated', vendor: 'intel', integratedName: 'Unknown', dedicatedName: null };
}
}
function setupGpuEnvironment(gpuPreference) {
if (process.platform !== 'linux') {
return {};
}
let finalPreference = gpuPreference;
let detected = detectGpu();
if (gpuPreference === 'auto') {
finalPreference = detected.mode;
console.log(`Auto-detected GPU: ${detected.vendor} (${detected.mode})`);
}
console.log('Preferred GPU set to:', finalPreference);
const envVars = {};
if (finalPreference === 'dedicated') {
envVars.DRI_PRIME = '1';
if (detected.vendor === 'nvidia') {
envVars.__NV_PRIME_RENDER_OFFLOAD = '1';
envVars.__GLX_VENDOR_LIBRARY_NAME = 'nvidia';
envVars.__GL_SHADER_DISK_CACHE = '1';
envVars.__GL_SHADER_DISK_CACHE_PATH = '/tmp';
}
console.log('GPU environment variables:', envVars);
} else {
console.log('Using integrated GPU, no environment variables set');
}
return envVars;
}
module.exports = {
getOS,
getArch,
isWaylandSession,
setupWaylandEnvironment,
detectGpu,
setupGpuEnvironment
};