mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
refactor(linux): simplify GPU-vendor detection for DMA-BUF toggle
Follow-up on #217. Blind A/B test on NVIDIA + proprietary confirmed the toggle helps, but the detection path had a few rough edges. - Drop lspci and glxinfo fallbacks: the /proc/driver/nvidia/version + sysfs scan catch every realistic case, and spawning subprocesses in main() added startup latency for no win (glxinfo also isn't always installed — mesa-utils isn't a hard dep). - Scan all /sys/class/drm/card* entries via read_dir instead of hardcoded card0/card1 — hybrid laptops and systems where only card1 exists were previously missed. - Remove 0x1022 from the AMD list: that's AMD's host/chipset vendor ID, not GPU. Only 0x1002 (ATI/Radeon) belongs here. - Unknown vendor → leave WEBKIT_DISABLE_DMABUF_RENDERER unset instead of forcing =1. VMs, ARM SBCs and anything exotic keep the WebKitGTK default and do not get regressed by a guess. - Only set the env var for the NVIDIA case. Intel/AMD on Mesa already default to DMA-BUF enabled in current WebKitGTK, so the explicit =0 was redundant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+24
-76
@@ -12,72 +12,28 @@ enum GpuVendor {
|
||||
#[cfg(target_os = "linux")]
|
||||
fn detect_gpu_vendor() -> Option<GpuVendor> {
|
||||
use std::fs;
|
||||
use std::process::Command;
|
||||
|
||||
// Check for NVIDIA driver presence (most reliable for proprietary drivers)
|
||||
if fs::metadata("/proc/driver/nvidia/version").is_ok() {
|
||||
return Some(GpuVendor::Nvidia);
|
||||
}
|
||||
|
||||
// Check sysfs DRM vendor IDs (works for most integrated/discrete GPUs)
|
||||
let vendor_paths = [
|
||||
"/sys/class/drm/card0/device/vendor",
|
||||
"/sys/class/drm/card1/device/vendor",
|
||||
];
|
||||
|
||||
for path in &vendor_paths {
|
||||
if let Ok(vendor_id) = fs::read_to_string(path) {
|
||||
let vendor_id = vendor_id.trim();
|
||||
// PCI vendor IDs: NVIDIA=0x10de, Intel=0x8086, AMD=0x1002/0x1022
|
||||
match vendor_id {
|
||||
"0x10de" => return Some(GpuVendor::Nvidia),
|
||||
"0x8086" => return Some(GpuVendor::Intel),
|
||||
"0x1002" | "0x1022" => return Some(GpuVendor::Amd),
|
||||
_ => {}
|
||||
}
|
||||
// Iterate every `/sys/class/drm/card*` — hybrid laptops expose multiple
|
||||
// cards, and some systems have no `card0` at all.
|
||||
let entries = fs::read_dir("/sys/class/drm").ok()?;
|
||||
for entry in entries.flatten() {
|
||||
let name = entry.file_name();
|
||||
let Some(name) = name.to_str() else { continue };
|
||||
if !name.starts_with("card") || name.contains('-') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: try lspci to detect GPU vendor (requires pciutils)
|
||||
if let Ok(output) = Command::new("lspci").args(["-nn"]).output() {
|
||||
if output.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
let line_lower = line.to_lowercase();
|
||||
// Only match VGA/Display controllers, not audio or other devices
|
||||
let is_display = line_lower.contains("vga")
|
||||
|| line_lower.contains("display")
|
||||
|| line_lower.contains("3d controller");
|
||||
|
||||
if is_display && line_lower.contains("nvidia") {
|
||||
return Some(GpuVendor::Nvidia);
|
||||
}
|
||||
if is_display
|
||||
&& (line_lower.contains("intel") || line_lower.contains("i915"))
|
||||
{
|
||||
return Some(GpuVendor::Intel);
|
||||
}
|
||||
if is_display && (line_lower.contains("amd") || line_lower.contains("radeon"))
|
||||
{
|
||||
return Some(GpuVendor::Amd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort: glxinfo (requires active display / X11 session)
|
||||
if let Ok(output) = Command::new("glxinfo").args(["-B"]).output() {
|
||||
if output.status.success() {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout).to_lowercase();
|
||||
if stdout.contains("nvidia") {
|
||||
return Some(GpuVendor::Nvidia);
|
||||
}
|
||||
if stdout.contains("intel") {
|
||||
return Some(GpuVendor::Intel);
|
||||
}
|
||||
if stdout.contains("amd") || stdout.contains("radeon") {
|
||||
return Some(GpuVendor::Amd);
|
||||
}
|
||||
let Ok(vendor_id) = fs::read_to_string(entry.path().join("device/vendor")) else {
|
||||
continue;
|
||||
};
|
||||
match vendor_id.trim() {
|
||||
"0x10de" => return Some(GpuVendor::Nvidia),
|
||||
"0x8086" => return Some(GpuVendor::Intel),
|
||||
"0x1002" => return Some(GpuVendor::Amd),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,22 +57,14 @@ fn main() {
|
||||
std::env::set_var("WEBKIT_DISABLE_COMPOSITING_MODE", "1");
|
||||
}
|
||||
|
||||
// Detect GPU vendor and configure DMA-BUF renderer appropriately.
|
||||
// NVIDIA proprietary drivers have issues with DMA-BUF in WebKitGTK,
|
||||
// so we disable it for NVIDIA. Mesa drivers (Intel/AMD) handle it well.
|
||||
if std::env::var("WEBKIT_DISABLE_DMABUF_RENDERER").is_err() {
|
||||
match detect_gpu_vendor() {
|
||||
Some(GpuVendor::Nvidia) => {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
Some(GpuVendor::Intel) | Some(GpuVendor::Amd) => {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "0");
|
||||
}
|
||||
None => {
|
||||
// Unknown GPU: default to safe mode (disable DMA-BUF)
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
}
|
||||
// NVIDIA proprietary adds a small but reproducible overhead on the
|
||||
// DMA-BUF renderer path (blind A/B confirmed on NVIDIA + proprietary).
|
||||
// Unknown GPUs keep the WebKitGTK default — VMs, ARM SBCs and anything
|
||||
// exotic should not be regressed by a guess.
|
||||
if std::env::var("WEBKIT_DISABLE_DMABUF_RENDERER").is_err()
|
||||
&& matches!(detect_gpu_vendor(), Some(GpuVendor::Nvidia))
|
||||
{
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user